layout | title | excerpt |
---|---|---|
post |
try(), try() again in Rails |
The very convenient try() method has been available to Rails developers since version 2.3, but it's easy to forget if you're not in the habit of using it. Here's a brief primer. |
In Rails, try()
lets you call methods on an object without having to worry about the possibility of that object being nil
and thus raising an exception. I know I sometimes forget about it, and I've looked at enough code from other developers to know that I'm not the only one. So today I'd like to give you a brief introduction to the method (and hopefully ingrain it a little deeper into my own brain). Let's look at some very simple code from a Rails view.
Here's a simple example of code you might replace with try()
. Say you've got a (rather contrived) Product
model in your project. A Product
may or may not have a known manufacturer, and some links you only want to display if a user is logged in and has administrator rights:
{% highlight erb %}
<% unless @product.manufacturer.nil? %> <%= @product.manufacturer.name %> <% end %>
<% if current_user && current_user.is_admin? %> <%= link_to 'Edit', edit_product_path(@product) %> <% end %> {% endhighlight %}
Like I said, it's contrived, but it should give you the idea. try()
can help us in a couple of places here:
{% highlight erb %}
<%= @product.manufacturer.try(:name) %>
<% if current_user.try(:is_admin?) %> <%= link_to 'Edit', edit_product_path(@product) %> <% end %> {% endhighlight %}
You can pass arguments and blocks to try():
{% highlight ruby %}
@manufacturer.products.first.try(:enough_in_stock?, 32)
@manufacturer.products.try(:collect) { |p| p.name }
{% endhighlight %}
You can chain multiple try()
methods together. In another contrived example, say you've got a method in your Manufacturer
model that sends the manufacturer a message whenever called.
{% highlight ruby %} class Manufacturer < ActiveRecord::Base has_many :products
def contact
"Manufacturer has been contacted."
end
end
Product.first.try(:manufacturer).try(:contact) #=> nil Product.last.try(:manufacturer).try(:contact) #=> "Manufacturer has been contacted." {% endhighlight %}
You can start with the Rails docs on try(). Rails' inclusion of try()
was inspired by Chris Wanstrath's post about adding try() to Ruby. Raymond Law at Intridea has a clever way to chain multiple calls to try(). And Scott Harvey has shared a more practical example of try().