One of the first things we learn in Rails which are greatly useful are ActiveRecord validations. However, since they are easy to add, it happens frequently that we are burdening our users with validations instead of making forms easier and clearer.
For instance, let’s suppose we are validating the Social Security Number (SSN) of an user on signup. A sample code would be:
1 2 3 4 5 6 7 | class User < ActiveRecord::Base validates_presence_of :ssn validates_length_of :ssn, :is => 9 validates_numericality_of :ssn validates_uniqueness_of :ssn validates_as_ssn :ssn # Checks if a reserved or special SSN was sent end |
With the configuration above, if the user forgets to fill in the SSN, leaving it blank, four error messages related to the SSN field will be shown:
- SSN can’t be blank
- SSN is the wrong length (should be 9 characters)
- SSN is not a number
- SSN is invalid
The question is: if the user just left the field blank, why we should show all those errors to him? Are they all relevant?

OMG! What have I done wrong to appear so many errors?
Luckily, the solution is quite simple: we can make use of the :allow_blank option, so other validations won’t be triggered if the field is blank:
1 2 3 4 5 6 7 | class User < ActiveRecord::Base validates_presence_of :ssn validates_length_of :ssn, :is => 11, :allow_blank => true validates_numericality_of :ssn, :allow_blank => true validates_uniqueness_of :ssn, :allow_blank => true validates_as_cpf :ssn, :allow_blank => true end |
This is also a nice use case for the Object#with_options method added by Rails:
1 2 3 4 5 6 7 8 9 10 | class User < ActiveRecord::Base validates_presence_of :ssn with_options :allow_blank => true do |v| v.validates_length_of :ssn, :is => 11 v.validates_numericality_of :ssn v.validates_uniqueness_of :ssn v.validates_as_cpf :ssn end end |
SSN is just an example, but we are frequently burdening our users in username, e-mail, password and many other fields.
Do not validate presence of confirmation fields
Another interesting subject about validations are the confirmation fields. We have the following note in the documentation of validates_confirmation_of:
1 2 | validates_confirmation_of :password # NOTE: This check is performed only if password_confirmation is not nil |
And this is a feature. This means that you don’t need to give the :password_confirmation key when creating objects in console or when writing tests:
1 2 3 | it "should be valid with valid attributes" do User.new(:password => "123456").should be_valid end |
If the test fails, you are validating the presence of :password_confirmation, which is unnecessary. Since the :password_confirmation field will be available in the views, it will always be sent. So if the user leave it blank, it’s sent as blank value to the model and therefore will be checked. Just in the place it needs to be.
Tags: rails, usability, validations
Posted in English | 23 Comments »
First, what is Inherited Resources?
Inherited Resources is a gem/plugin that allows you to speed up development by making your controllers inherit all restful actions so you just have to focus on what is important. A Rails scaffold controller which responds to html, xml and json is as simple as:
1 2 3 | class ProjectsController < InheritedResources::Base respond_to :html, :xml, :json end |
However all actions are still customizable! For example, you can change the behavior of the create action on success just doing:
1 2 3 4 5 6 7 8 9 | class ProjectsController < InheritedResouces::Base respond_to :html, :xml, :json def create create! do |success, failure| success.html { redirect_to edit_project_url(@project) } end end end |
It also supports I18n (all flash messages are set with I18n), belongs to association (like a task belongs to project), nested belongs to (task belongs to project which belongs to company), polymorphic belongs to (comments belong to task or file or message) and optional belongs to (the same as previously, but you can request the resource with or without parents).
As you noticed, besides simplifying your controllers, InheritedResouces makes easy to reproduce your models behavior and relationship in controllers. And right now, it’s also scopes and responder fluent!
has_scope: named_scope twin brother
Let’s suppose that we have a ProjectsController and at some point you want to add some filters on the index action like showing just featured projects, selecting projects by methodology or even let the user choose how many projects he can see per page. The first thing to do? Add named scopes to your model:
1 2 3 4 5 | class Project < ActiveRecord::Base named_scope :featured, :conditions => { :featured => true } named_scope :by_methodology, proc {|methodology| { :conditions => { :methodology => methodology } } } named_scope :limit, proc{|limit| :limit => limit.to_i } end |
The next step would be to add a lot of code in your controllers that check which named scopes you should call, based on the parameters sent right? Well, not anymore. Your controller can be as simple as:
1 2 3 4 5 | class ProjectsController < InheritedResources::Base has_scope :featured, :boolean => true has_scope :by_methodology has_scope :limit, :default => 10, :only => :index end |
Then for each request:
/projects #=> acts like a normal request, but returning only 10 projects /projects?featured=true #=> calls the featured named scope and bring 10 featured projects /projects?featured=true&by_methodology=agile&limit=20 #=> brings 20 featured projects with methodology agile
If you configure your routes, you could even have pretty urls with it:
/projects/agile/featured #=> brings 10 featured projects with methodology agile
Yay!
Responder
A couple weeks ago, we wrote about ActionController::Responder. But you don’t have to wait Rails 3 to be released to play with it, you can start now by using Inherited Resources.
Quick redirect
After using Inherited Resouces, I realized that most of the times I overwrite a create, update or destroy actions is to change the redirect destination. In our ProjectsController above, if we want to redirect to the edit page after create, we would have to do:
1 2 3 4 5 6 7 8 9 | class ProjectsController < InheritedResouces::Base respond_to :html, :xml, :json def create create! do |success, failure| success.html { redirect_to edit_project_url(@project) } end end end |
It wouldn’t be cool if it have a shortcut? Now it has:
1 2 3 4 5 6 7 | class ProjectsController < InheritedResouces::Base respond_to :html, :xml, :json def create create! { edit_project_url(@project) } end end |
That simple, just give the url as a proc and since the proc does not expect any parameters, it assumes that you want to overwrite the redirect url.
Finally some DSL?
Last weeks, there was a discussion on Boston.rb group about different resource controllers gems. Reading some of the feedback there, I’ve decided to stab a DSL to Inherited Resources. It will mainly remove the duplication when you have to give a block, the previous example above could be written as:
1 2 3 4 5 6 7 | class ProjectsController < InheritedResouces::Base respond_to :html, :xml, :json create! do |success, failure| success.html { redirect_to edit_project_url(@project) } end end |
Or even in the compact form:
1 2 3 4 | class ProjectsController < InheritedResouces::Base respond_to :html, :xml, :json create! { redirect_to edit_project_url(@project) } end |
Those changes were not applied yet, it depends mainly on you. If you like or not, let us know in the comments!
Tags: inherited_resources, plugins, rails
Posted in English | 28 Comments »
Uma das primeira coisas que aprendemos em Rails e que são de grande utilidade são as validações do ActiveRecord. Porém, como as validações são muito fáceis de adicionar e remover, temos que ter certeza que não estamos sobrecarregando nossos usuários com validações.
Por exemplo, supondo que estamos validando o CPF do usuário no cadastro e temos o seguinte código:
1 2 3 4 5 6 7 | class User < ActiveRecord::Base validates_presence_of :cpf validates_length_of :cpf, :is => 11 validates_numericality_of :cpf validates_uniqueness_of :cpf validates_as_cpf :cpf # Checa se o cálculo de dígitos é correto end |
Na configuração acima, se o usuário esquece de preencher o campo CPF, deixando-o em branco, nada menos que quatro erros aparecerão para ele:
- Campo CPF não pode ficar em branco;
- Campo CPF deve possuir 11 caracteres;
- Campo CPF deve possuir apenas números;
- Campo CPF é inválido.
Se o usuário deixou apenas o campo em branco, porque mostrar todos esses erros para ele? Todos os erros mostrados são relevantes?

Ó céus! O que fiz de errado para aparecer tantos erros?
Felizmente, a solução é simples, apenas adicione :allow_blank nas validações que elas não serão calculadas caso o campo seja enviado vazio:
1 2 3 4 5 6 7 | class User < ActiveRecord::Base validates_presence_of :cpf validates_length_of :cpf, :is => 11, :allow_blank => true validates_numericality_of :cpf, :allow_blank => true validates_uniqueness_of :cpf, :allow_blank => true validates_as_cpf :cpf, :allow_blank => true end |
Você também pode usar o método Object#with_options adicionado pelo Rails para agrupar as validações:
1 2 3 4 5 6 7 8 9 10 | class User < ActiveRecord::Base validates_presence_of :cpf with_options :allow_blank => true do |v| v.validates_length_of :cpf, :is => 11 v.validates_numericality_of :cpf v.validates_uniqueness_of :cpf v.validates_as_cpf :cpf end end |
O campo CPF é apenas um exemplo, mas estamos sobrecarregando os nossos usuários frequentemente nos campos username, e-mail, password e outros.
Não exija a presença de campos confirmação
Um outro tópico que vale a pena ser discutido sobre validações são campos de confirmação. Existe a seguinte nota na documentação do Rails para validates_confirmation_of:
1 2 | validates_confirmation_of :password # Nota: essa validação ocorre apenas se o campo :password_confirmation não for nulo. |
E isso é uma feature. Isso significa que nos seus testes ou ao criar um objeto no console, você não precisa passar o campo :password_confirmation:
1 2 3 | it "should be valid with valid attributes" do User.new(:password => "123456").should be_valid end |
Se por acaso o teste falhar, é porque você adicionou a validação de presença para o campo :password_confirmation, que é desnecessária. Como o campo :password_confirmation estará presente nas views, ele sempre será enviado e portanto sempre será checado, justamente onde é necessário.
Posted in Português | 1 Comment »
UPDATE: ActionController::Renderer was renamed to ActionController::Responder, so this post was changed to properly reflect such changes.
About two and a half years ago, resources started to be a first class citizen in Rails when version 1.2 was released and it was all about RESTful admiration and HTTP Lovefest. Since then we’ve added map.resources to our routes, started to use different formats in respond_to and really learned how to love all HTTP verbs.
Your application entry point (the router) has become completely RESTful, but it still haven’t reached ActionPack core. Today we are bringing the missing ingredient: make your controllers more resource aware.
The first step: respond_with(@resource)
About one week ago the first step was given. We brought Merb’s provide/display into Rails, just as DHH proposed: you can define supported formats at the class level and tell in the instance the resource to be represented by those formats. Let’s see some code:
class UsersController < ApplicationController respond_to :html, :xml, :json def index @users = User.all respond_with(@users) end end
It works like this: when a request comes, for example with format xml, it will first search for a template at users/index.xml. If the template is not available, it tries to render the resource given (in this case, @users) by calling :to_xml on it. Before Rails 3.0, the equivalent to the index action above would be:
class UsersController < ApplicationController def index @users = User.all respond_to do |format| format.html format.xml { render :xml => @users } format.json { render :json => @users } end end end
The gain with respond_with introduction is more obvious if you compare index, new and show actions:
class UsersController < ApplicationController respond_to :html, :xml, :json def index @users = User.all respond_with(@users) end def new @user = User.new respond_with(@user) end def show @user = User.find(params[:id]) respond_with(@user) end end
With older version:
class UsersController < ApplicationController def index @users = User.all respond_to do |format| format.html format.xml { render :xml => @users } format.json { render :json => @users } end end def new @user = User.new respond_to do |format| format.html format.xml { render :xml => @user } format.json { render :json => @user } end end def show @user = User.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @user } format.json { render :json => @user } end end end
However, even if respond_with is full featured (Ryan Daigle has done an excellent job covering all respond_with features), it started to show some flaws on create, update and destroy actions. A default create action could be written with respond_with as:
def create @user = User.new(params[:user]) if @user.save flash[:notice] = "User was created successfully." respond_with(@user, :status => :created, :location => @user) do |format| format.html { redirect_to @user } end else respond_with(@user.errors, :status => :unprocessable_entity) do |format| format.html { render :action => :new } end end end
You can notice that:
- You have to call respond_with twice;
- On the first respond_with, you have to give the location twice. One as a hash and other as parameter to redirect_to;
- And by giving a block to respond_with, you focus more on the exception than on the default behavior.
Suddenly we realized that respond_with is useful just for GET requests. There was no HTTP Lovefest, it was more like HTTP monotheism.
2. Second step: Love all
At this point, we started to ask ourselves: why can’t respond_with include HTTP verb semantics? Isn’t that what RESTful is all about?
After this commit, we brought all HTTP verbs to respond_with, but only for resourceful formats like xml and json (ie. formats that don’t need to render a template). Then our create action with POST request could be rewritten as:
def create @user = User.new(params[:user]) respond_with(@user) do |format| if @user.save flash[:notice] = "User was created successfully." format.html { redirect_to @user } else format.html { render :action => :new } end end end
Internally, when a xml request happened, respond_with would check the current request method (in this case, POST) and whether the resource has errors or not. Depending on these values, it will render the resource or the resource errors, setting accordingly the status and location headers. Now we just have to worry with non-RESTful requests, like html, mobile and iphone… (which we call navigational formats).
Personally, I was quite happy with the results at this iteration, since it solves two of the three problems exposed previously. However, Jeremy Kemper and Yehuda Katz wanted more. And they were right, yeah!
3. Third step: Responder
In step 2, we were able to abstract POST, PUT and DELETE requests for formats like xml and json, but we still would have to repeat html behavior through all controllers, even if almost all of them behave similarly.
So what we want is a simple way to tell the controller how to render our resources depending on the format AND HTTP verb. In this commit, we’ve added ActionController::Responder.
By default, ActionController::Responder holds all formats behavior in a method called to_format. It’s similar to this:
def to_format return render unless resource.respond_to?(:"to_#{format}") if get? render format => resource elsif has_errors? render format => resource.errors, :status => :unprocessable_entity elsif post? render format => resource, :status => :created, :location => resource else head :ok end end
As you can see, it renders the resource based on the HTTP verb and whether it has errors or not. If some format, like :html, does not fall into the to_format behavior, we just need to define a to_html in ActionController::Responder, which by default is:
def to_html if get? render elsif has_errors? render :action => (post? ? :new : :edit) else redirect_to resource end end
As result, you have your resources representation encapsulated in one place. Your controller code just have to send the resource using respond_with(@resource) and respond_with will call ActionController::Responder which will know what to do. Our create action (POST request) can then be written as:
def create @user = User.new(params[:user]) flash[:notice] = "User was created successfully." if @user.save respond_with(@user) end
If you need to change the redirect URL, you can overwrite just the html behavior:
def create @user = User.new(params[:user]) flash[:notice] = "User was created successfully." if @user.save respond_with(@user) do |format| format.html { redirect_to user_confirmation_url } end end
On the other hand, if you want to change the redirect url and the Location header for XML and JSON, you can simply give :location as option:
def create @user = User.new(params[:user]) flash[:notice] = "User was created successfully." if @user.save respond_with(@user, :location => user_confirmation_url) end
The best of all is that the responder implementation is quite simple and straight-forward, but still powerful. We haven’t enforced any restriction in the API. Anything that responds to :call can be a responder, so you can create your custom classes or even give procs, fibers and so on.
Embrace REST in your design and enjoy a consistent behavior through all your controllers. Spread the word!
Tags: http verbs, rails, resource, responders, respond_with, REST
Posted in English | 20 Comments »

All
English only
Em português apenas