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 likeuser? #=> true | false
user(:can_create_pages?) #=> true | false
user(:can_edit?, @page) #=> true | false
The tr