public
Description: Conditional checks on Rails filters
Clone URL: git://github.com/thoughtbot/when.git
jcarroll (author)
Thu Feb 14 14:43:07 -0800 2008
commit  d7040373acafc9c579ca61f242536eff4d395878
tree    55bce47987194cf945c814853ef108873b02709c
parent  f2c7cc46bf8545aeebb23180cead62d19ce330de
when /
name age message
file MIT-LICENSE Wed Feb 13 16:25:45 -0800 2008 updated the README [jcarroll]
file README Wed Feb 13 19:21:29 -0800 2008 style changes [dcroak]
file Rakefile Mon Feb 11 18:43:52 -0800 2008 test and README files [dcroak]
file init.rb Mon Feb 11 22:32:55 -0800 2008 refactoring tests [dcroak]
file install.rb Mon Feb 11 18:23:48 -0800 2008 added when plugin skeleton [dcroak]
directory lib/ Wed Feb 13 17:11:05 -0800 2008 added tests for not supporting String, Proc or ... [jcarroll]
directory test/ Wed Feb 13 19:21:29 -0800 2008 style changes [dcroak]
file uninstall.rb Mon Feb 11 18:23:48 -0800 2008 added when plugin skeleton [dcroak]
README
When
====

When adds :if and :unless conditions to ActiveRecord callbacks 
and validations and ActionController filters. It works exactly 
the way as the current implementation of #validates_acceptance_of.

It works on the 12 regular callbacks:

before_validation
before_validation_on_create
after_validation
after_validation_on_create
before_save
before_create
before_update
after_create
after_update
after_save
before_destroy
after_destroy

3 validations:

validate
validate_on_create
validate_on_update

and 1 filter:

before_filter

It works when :if or :unless is passed a Symbol, a Proc or a String.
They return or evaluate to a true or false value.

Example
=======

class Address < ActiveRecord::Base

  before_save :geolocate

  def geolocate
    if complete?
      ...
    end
  end

  def complete?
    street? && city? && state? && zip?
  end

end

In this case, we want to find the latitude and longitude of an address only if 
the address is complete.

Wrapping the entirety of a callback method with conditional logic is bad form.
The callback should execute WHEN the model's life cycle reaches its 
"before_save" point and WHEN its address is "complete."

With When, the WHEN responsibility is moved to where it belongs:
as part of the callback.

class Address < ActiveRecord::Base

  before_save :geolocate, 
    :if => :complete?

  def geolocate
    ...
  end

  def complete?
    street? && city? && state? && zip?
  end

end

before_create's single responsibility is to execute code WHEN certain conditions are met.
geolocate's single responsibility is to ... geolocate. It should not contain its own
preconditions. 

More Examples
=============

before_create :encrypt_password,
  :unless => lambda {|user| user.password_confirmation.blank?}

before_filter :log_in!,
  :only => [:new, :create],
  :unless => :logged_in?

Copyright (c) 2008 Jared Carroll and Dan Croak, released under the MIT license