HowTo: State Validations in Rails' ActiveRecord

Posted by Lance Ivy Wed, 08 Oct 2008 21:57:00 GMT

Problem

Suppose you’ve got an ActiveRecord object that could benefit from state behavior. Perhaps it’s a multi-step form or wizard? Suppose further that you don’t want the full weight of a state machine plugin like AASM. How can you elegantly configure validations for each state?

Solution

Whenever possible, I like to use Semantic Attributes for validations. But this example works equally well with Rails’ own validates methods.

class Post < ActiveRecord::Base
  # First, we want query methods for each state. Not necessary, but nice!
  def draft?;     self.state == 'draft'      end
  def live?;      self.state == 'live'       end
  def archived?;  self.state == 'archived'   end
  def complete?;  !draft?                    end

  # validations for every state
  title_is_required

  # validations for post-draft state
  with_options :if => :complete? do |c|
    # Perhaps you prefer the Semantic Attributes library?
    c.body_is_required
    # Or perhaps you want something custom
    c.validates_each :body do |record, attr, value|
      record.errors.add attr, "Body is not well-formed." unless Tidy.valid?(value)
    end
  end
end

And there you have it. By using with_options we can clean up our code and make it self-documenting.


Comments

  1. Avatar
    Brian 1 day later:

    This looks like a perfect case for AASM

  2. Avatar
    Lance 1 day later:

    @Brian: I clarified the part where this is for people who don’t want AASM. :-)