Tom Kadwill

A programmers blog.

Rails Callback Inheritance and Types

Rails controllers can inherit callbacks from parent controllers. Most controllers will inherit from ApplicationController so this is a good place to put callbacks that you want to share across all of your controllers.

Remember that callbacks from the base class are run first and thus it is possible to ‘skip’ the callback of the subclass altogether. In the example below the base class implements a method to redirect the user to google.com. I have also implemented a HomeController which implements a callback that adds a debug message to the log.

1
2
3
4
5
6
7
8
9
class ApplicationController < ActionController::Base
  before_action :redirect_to_user

  private

  def redirect_to_user
    redirect_to 'http://www.google.com'
  end
end
1
2
3
4
5
6
7
8
9
class HomeController < ApplicationController
  after_action :call_logger

  private

  def call_logger
    logger.debug 'HomeController log'
  end
end

When the user visits a page served by the HomeController Rails will first run the call back in the ApplicationController redirecting the user to google.com. As a result, the call_logger callback in the HomeController is never run.

Action Callback types

There are three types of callbacks. The first are method callbacks, like the example above. The second are callback classes which allow programmers to reuse callback code.

1
2
3
4
5
6
7
8
9
class AddDebug
  def self.before(controller)
    controller.logger.debug "AddDebug class"
  end
end

class ApplicationController < ActionController::Base
  before_action AddDebug
end

The third are inline methods/blocks.

1
2
3
4
5
class ApplicationController < ActionController::Base
  before_action do
    logger.debug 'before_action blog log'
  end
end

Route Constraints

Rails route constraints are useful if you want to only allow a specific segment key (eg, only integers). The route below uses a regex expression to filter by the id segment; if the id is an integer then it will route to the show action, otherwise it will fall through to the index action.

1
2
  get 'questions/:id' => 'questions#show', constraints: { id: /\d+/ }
  get 'questions/:id' => 'questions#index'

You also have access to the request object, which you can use if you need more control. The example below routes to the show action only if the id is lower than 100.

1
2
  get 'questions/:id' => 'questions#show', constraints: proc {|request| request.params[:id].to_i < 100 }
  get 'questions/:id' => 'questions#index'

Rails routes can of course be re-written using scopes and the rule is no different when using constraints. Our first example could be re-written as:

1
2
3
4
  scope controller: :questions, path: :questions do
    get ':id' => :show, constraints: { id: /\d+/ }
    get ':id' => :index
  end

You can also nest specific routes inside a constraints block, within your scope. This allows constraints to be added to certain routes only:

1
2
3
4
5
6
  scope controller: :questions, path: :questions do
    constraints id: /\d+/ do
      get ':id' => :show
    end
    get ':id' => :index
  end

Finally, Rails allows you to reuse constraints in a modular way. Simply create an object that has a matches? method and pass it into the constraints method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class IdConstraint
  def self.matches?(request)
    request.params[:id] =~ /\d+/
  end
end

Rails.application.routes.draw do
  scope controller: :questions, path: :questions do
    constraints IdConstraint do
      get ':id' => :show
    end
    get ':id' => :index
  end
end

REST

REST stands for Representational State Transfer (ReST), the idea is to use HTTP calls between machines rather than complex mechanisms like CORBA, RPC or SOAP. In a sense the web itself can be viewed as having REST-based architecture as it is based on HTTP.

RESTful applications use HTTP requests for all four CRUD operations:

  • reading data, querying the DB (Read)
  • posting data, create and/or update (Create, Update)
  • deleting data (Delete)

About REST

  • Platform independent (Unix, Mac or Windows)
  • Language-independent (JavaScript can talk to Ruby, for example)
  • Standards-based (runs on top of HTTP)
  • No built in security or encryption

Simplicity

A typical request using SOAP would look something like the one below, all of which has to be sent via HTTP POST.

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:body pb="http://www.acme.com/phonebook">
  <pb:GetUserDetails>
   <pb:UserID>12345</pb:UserID>
  </pb:GetUserDetails>
 </soap:Body>
</soap:Envelope>

With REST the request might look something like:

1
http://www.acme.com/phonebook/UserDetails/12345

No request body is required and the url is sent to the server using a simpler HTTP GET. Aside from the obvious simplicity, another advantage is that when using REST all you need is a network connection and you can even test the API directly in the browser.

More complex REST requests

The previous example was a simple one, with a single parameter. REST can also handle multiple parameters via HTTP GET:

1
http://www.acme.com/phonebook/UserDetails?firstName=John&lastName=Doe

If you want to pass longer parameters then you would typically use HTTP POST.

GET vs POST

GET requests should be used for read-only queries that do not change the state of the server’s data. POST requests should be used for creating, updating and deleting.

REST response

Unlike SOAP, REST is not bound to XML. Possible formats include CSV and JSON. HTML should only be used when the service is documented to return a human-readable document.

REST design guidelines

  1. Don’t point to physical files – Use http://www.acme.com/inventory/product/003 not http://www.acme.com/inventory/product003.xml
  2. Queries should not return an overload of data, if required, use pagination.
  3. GET access requests should never change state.

References

This post is a simplified version of Dr. M. Elkstein’s REST series.

My First Gem

I have contributed to a number of Ruby gems but I have never written my own; I haven’t come up with a great idea worth distributing as a gem. In the meantime I have written a gem for calculting BMI, which will almost certainly not be useful to anyone. However, I was able to put some lessons from Destroy all Software and POODR into practise.

Destroy all Software – fast tests

DHH recently started the TDD is dead debate. One of his points is programmers should not worry about the speed of their test suite as it can lead to tests that do not properly test your system. Detractors say that tests should be fast in order to obtain a quick feedback loop – slow tests cause programmers to run them less frequently and in extreme cases, not at all. Gary Bernhardt explains how he uses a script to run quick unit tests. The idea is to extract your model tests away from Rails so that you can run unit tests without loading Rails.

POODR – 5 line methods, 100 line class & law of demeter

I also wanted to utilise some of the principles I’ve learned from Sandi’s book. Specifically I tried to write a class that was less than 100 lines long, with methods less than 5 lines. I also tried not to break the law of demeter.

Did I write better Ruby code?

With regards to testing I think it was a success; the code is well tested and the tests are very quick. Following the principles of POODR, I think, has produced clean Ruby code. However, the code is inherently simple and it would probably be hard to write something that wasn’t simple. Never the less I will be trying to write more code that follows these principles in the future.

Ruby Blocks

As a Ruby programmer I frequently use blocks. Most programmers first touch blocks during their first ruby tutorial when they learn to iterate over an array. This is a common use for blocks but they are far more powerful.

What is a block?

A block is similar to a callback, it is a chunk of code that you wish to execute a little later. Blocks can take 1 of the following forms:

1
thing.each {|thing| thing + 1 }

or

1
2
3
thing.each do |thing|
   thing + 1
end

What does a block do?

The idea is that you pass a block (chunk of code) into a method. That method then decides what to do with the block.

Procs

Blocks are essentially annoymous, you can pass them into methods but you cannot assign them to variables to reference. in order to that you need to use the proc keyword. A proc lets you turn a block into an object, allowing you to reference it. Once you have created a proc you can use the call method to execute the block.

1
2
hello_world = proc { puts 'hello world!' }
hello_world.call # prints "hello world!\n"

Procs can also take parameters.

1
2
hello_world = proc {|name| puts 'hello #{name}' }
hello_world.call('Tom') # prints "hello Tom\n"

Blocks and method parameters

Every method, whatever its parameter list, can optionally be passed a block as a parameter. This is know as the default block and you can access it, within the method, using the keyword yeild.

1
2
3
4
5
6
def two_times(title)
   puts title
   yeild
   yeild
end
two_times('hello') { puts 'world' }

We can also rewrite this method to use procs.

1
2
3
4
5
6
7
def two_times(title, action)
   puts title
   action.call
   action.call
end
action = proc { puts 'world' }
two_times('hello', action)

The cool thing here is that, using the default block, we can write methods that act almost like Ruby keywords. For example, in Ruby we have each.do.... After defining the method above, we can call two_times.do... which looks just like a build in Ruby method.

Note that default blocks can also accept parameters just like any other block.

1
2
3
4
5
def two_times
   yeild 0
   yeild 1
end
count {|i| puts 'position #{number}' }

Methods that work with or without a block

It is possible to write methods that work both with and without having a block passed to them. You can do this using the line yeild if block_given?.

Block to a proc

Ruby makes it possible for a method to turn a block that it recieves into a proc using the & symbol.

1
2
3
4
5
def two_times(&p)
   p.call
   p.call
end
count { puts 'position #{number}' }

Proc to a block

This also works in reverse so you can turn a proc into a default block.

1
2
stuff = proc {|thing| thing + 1}
something.each(&stuff)

Lambdas

Almost idential to procs with two differences:

  1. Procs do not care how many arguments are passed to it. Lambdas will throw an error if it is passed the wrong number of arguments.
  2. When using return within a proc it returns from the method. If used within a Lambda is it returned from the block.

Components Inside Rails

In this post I will explore the different parts that make up Rails – ActionMailer, ActionPack, ActionView, ActiveModel, ActiveRecord, ActiveSupport and Railties.

ActionMailer

As the name implies ActionMailer is a framework for designing email service layers. ActionMailer is a wrapper around ActionController and the Mail gem providing a way to make emails using templates in the same way as ActionController renders views using templates.

ActionPack

handles and responds to web requests; enables routing, defining controllers that implement actions and generating responses by rendering views. ActionPack therefore provides the view and controller for Rails MVC. ActionPack includes two main modules:

  • ActionDispatch handles routing, decodes parameters in POST, PATCH or PUT and handles caching, cookies & sessions.

  • ActionController provides a base controller class which can be subclassed to implement filters and actions to handle requests.

ActionView

handles view template lookup and rendering as well as view helpers that assist when building HTML forms in ERB and XML.

ActiveModel

Allows ActionPack helpers to interact with non-ActiveRecord classes. Using ActiveModel you can access Rails API methods that you will have seen in ActiveRecord (eg. validates_presence_of). To read more about ActiveModel checkout the Rails Guide and this great blog post.

ActiveRecord

Object-Relational Mapping for Rails that connects classes to relational databases. Allows for the creation of models and model associations. ActiveRecord contains all of the methods you typically use in your Rails model classes (validates, has_many, belongs_to, ect). ActiveRecord is also responsible for database schema and migrations.

ActiveSupport

Provides extensions to the Ruby language, extra utilities and helpers; many of which you will already be familiar with. Checkout the Rails Guide for a full list.

Railties

Glues the whole framework together; handles the bootstrapping process for a Rails application, manages the rails commandline interface and provides Rails generators.

*This content is largely paraphrased from the Rails README

Rails Sessions Hash

This post looks at Rails sessions, specifically the Rails session hash and how to use it in an application.

A session is used to persist data for longer than a typical browser request. For example, most modern web applications will store your user session so that once you have logged in you don’t need to re-enter your user information each time you visit the site.

The first thing to know is that rails provides a sessions hash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def login
  if user = session[:user]
    login_user user
  else
    render 'new'
  end
end

...

def sign_in
  user = User.find(params[:id])
  session[:user] = user
  login_user user
end

Using the sessions hash you can write a controller action similar to the login action above. The first time the login method is called the user is redirected to the new user form. The new user form will post to sign_in which will find the user and assign it to the sessions hash, before logging the user in. The next time login is triggered it will get the user from the sessions hash and login the user in straight away.

Typically the sessions will persist until the user closes their browser. If we inspect the page we can see how Rails implements a session on the clients browser. Rails creates a cookie which is set to expire with the session – hence when the user closes their browser, the session ends and the cookie disappears. After setting a user to the session hash (line 13) you will see that the size of the cookie increases, indicating that the user’s data has indeed been saved to the session.

In a real world application we often want to persist data even after the user closes their browser. Michael Hartl’s book Learn Rails by Example walks you through storing sessions in the database. I recommend that you check it out to learn more about using sessions in production code.

Rails 4 Forms With Virtual Attributes

There are times when you want to post an attribute along with the rest of your form parameters which is not a field in the database. With Rails, you can achieve this by creating a virtual attribute. This post explains how to create virtual attributes for a form, using Rails 4.

First, imagine that we have a User model with a name and email field. The form might look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
<%= form_for @user do |f| %>
<ol>
  <li>
    <%= f.label :name, 'Full Name' %>
    <%= f.text_field :name %>
  </li>
  <li>
    <%= f.label :email, 'Email' %>
    <%= f.password_field :email %>
  </li>
  <%= f.submit %>
</ol>
<% end %>

Now imagine that we want to add a nickname field but we don’t want to set nickname in the database. The first thing we need to do is to add the field to the form:

1
2
3
4
<li>
  <%= f.label :nick_name, 'Nick Name' %>
  <%= f.text_field :nick_name %>
</li>

Next we need to create the virtual attribute in the User model. We can do that using attr_accessor. This method creates getter and setter methods for the new attribute allowing us to set the value after submitting the form. Your model with look something like this:

1
2
3
class User < ActiveRecord::Base
  attr_accessor :nick_name
end

Finally, we need to set up the controller to receive the params and create a new User record.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  def create
    @user = User.new(user_params)
    if @user.save
      render "index"
    else
      render "new"
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :nick_name)
  end

Rails 4 uses strong parameters, meaning developers cannot mass assign attributes by default. Rails 4 also prefers that you specify allowed attributes in the controllers rather than the model, as it was previously.

In the example above I create a method user_params which allows me to specify which params the User model will permit. To create a new user I simply call User.new and pass in user_params.

Atom Packages

Github recently released Atom, a new ‘hackable’ text editor. I’ve switched to using Atom full time to experience the good and the bad.

Prior to the switch I was using Vim; the transition from a modal text editor to a shortcut based text editor has been interesting. There are some features that I like but there are some features of Vim that I really miss. To fill the gap, I have been busy writing a few packages.

  1. atom-rails – I wrote this package to bring the best features of tpope’s vim-rails to Atom. The plugin allows for jumping between associated models, controllers and views. I want to expand the plugin to include more advanced features like rails generate shortcuts and jumping to partial files.

  2. find-letter – This plugin attempts to mimic Vim’s t and f commands where you can jump to the next occurance of a character. I’m not sure how useful this will be in a non-modal text editor but it will be fun to see.

I hope people find these plugins useful and I would love to hear your feedback.