Ruby Block Goodness

February 14th, 2007

I uncover something new in Ruby nearly every day. Here’s a neat trick I learned today:

Suppose you have a User model, and that model has several methods that determine a user’s rights. Maybe something like User#can_delete?(object) and User#can_create_pages?.

Now suppose that in your view, you want to display a certain link only if a user is logged in AND if that user has rights to do that thing. So the delete link would look like this:

<%= link_to("delete", page_url(@page), :method => :delete) 
    if User.current_user and User.current_user.can_delete?(@page) %>

Yuk. Wordy. If you don’t check for User.current_user first, ActionView will raise an error because you’ll be requesting the can_delete? method from a nil object. So every time you want to display the delete link, you have to remember to process multiple conditions.

There is a better way.

In my ApplicationHelper, I defined a method called user?.


  def user?(*args, &block)
    return false unless User.current_user
    return true if args.first.blank?
    return User.current_user.send(*args, &block)
  end
  alias_method :user?, :user

Now we can rewrite that link code.

<%= link_to("delete", page_url(@page), :method => :delete) 
    if user(:can_delete?, @page) %>

Nice, eh?

We can do things like
user? #=> true | false
user(:can_create_pages?) #=> true | false
user(:can_edit?, @page) #=> true | false

The tr