Ruby on Rails
HowtoValidate

The controller:

class WeblogController < ActionController::Base
  def show # not used directly, just example
    @post = Post.find(params["id"])
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(params["post"])
    if @post.save
      redirect_to :action => "show", :id => @post.id
    else
      render_action "new" 
    end
  end
end

The new template:

<% unless @post.errors.empty? %>
  The post couldn't be saved due to these errors:
  <ul>
  <% @post.errors.each_full do |message| %>
    <li><%= message %></li>
  <% end %>
  </ul>
<% end %>

<%= form "post" %>

or even shorter:


<%= error_messages_for 'post' %>

The model (0.9):

class Post < ActiveRecord::Base
    validates_presence_of :title, :body, :message => "Missing required field" 
    validates_length_of :title, :maximum => 10, :message => "Title too long - max 10 characters" 
end

The model (pre 0.9):

class Post < ActiveRecord::Base
  protected
    def validate
      errors.add_on_empty(["title", "body"])
      errors.add("title", "must be at most 10 characters") if title.size > 10
    end
end

The Validation Documentation has all sorts of details about what methods are available. Also check out the validation class methods available in Rails 0.9.

Note: validates_confirmation_of is very weak. If the *_confirmation field is nil, the confirmation does not take place. This makes it easy for poorly written code to by pass the confirmation.

_validates_acceptance_of also accepts nil values by default. If you write your controllers test-first (and you should—it’s so good that you can), acceptance_of tests will pass falsely if you do not pass them a value.

Conditional validation (tested with version 1.2.5)

Conditional validation can be done using the :if attribute of the validation methods. For example, if you need to validate the numericality of a field but also need that field to be optional:


validates_numericality_of :age, :if => :age?

Or, if you need to perform some sort of processing in order to determine whether or not to validate:


validates_numericality_of :age, :if => Proc.new { |age| !age.blank? }

Using Proc.new with the block is necessary since :if has specific requirements about what can be passed to it (quoting the error message Rails provides):


Validations need to be either a symbol, string (to be eval'ed), proc/method, or class implementing a static validation method

AJAX validation (error messages)

If you find yourself having to deal with validation (error messages) in Rails, you might want to check out this article by me, Bigsmoke.

category:Howto
category:OpenQuestion