Flowdock
method

try

Importance_5
Ruby on Rails latest stable (v4.2.1) - 7 notes - Class: Object
try(*a, &b) public

Invokes the public method whose name goes as first argument just like public_send does, except that if the receiver does not respond to it the call returns nil rather than raising an exception.

This method is defined to be able to write

@person.try(:name)

instead of

@person.name if @person

try calls can be chained:

@person.try(:spouse).try(:name)

instead of

@person.spouse.name if @person && @person.spouse

try will also return nil if the receiver does not respond to the method:

@person.try(:non_existing_method) #=> nil

instead of

@person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil

try returns nil when called on nil regardless of whether it responds to the method:

nil.try(:to_i) # => nil, rather than 0

Arguments and blocks are forwarded to the method if invoked:

@posts.try(:each_slice, 2) do |a, b|
  ...
end

The number of arguments in the signature must match. If the object responds to the method the call is attempted and ArgumentError is still raised in case of argument mismatch.

If try is called without arguments it yields the receiver to a given block unless it is nil:

@person.try do |p|
  ...
end

You can also call try with a block without accepting an argument, and the block will be instance_eval’ed instead:

@person.try { upcase.truncate(50) }

Please also note that try is defined on Object. Therefore, it won’t work with instances of classes that do not have Object among their ancestors, like direct subclasses of BasicObject. For example, using try with SimpleDelegator will delegate try to the target instead of calling it on the delegator itself.

Show source
Register or log in to add new notes.
January 6, 2010
6 thanks

Doesn't return nil if the object you try from isn't nil.

Note that this doesn’t prevent a NoMethodError if you attempt to call a method that doesn’t exist on a valid object.

a = Article.new

a.try(:author) #=> #<Author ...>

nil.try(:doesnt_exist) #=> nil

a.try(:doesnt_exist) #=> NoMethodError: undefined method `doesnt_exist' for #<Article:0x106c7d5d8>

This is on Ruby 1.8.7 patchlevel 174

July 24, 2012
3 thanks

rest of code is in NilClass#try

If you click “Show source” here, you may get confused. The logic for #try is shared between this method and NilClass#try . Both versions are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .

June 10, 2009
2 thanks

[:a, :b, :c].try([1]) ? The answer is No.

Correct way is this:

[:a, :b, :c].try(:at, 1)
August 21, 2014 - (v4.0.2)
2 thanks

In Rails 4 it DOES return nil, even if the object you try from isn't nil

The try method does not raise a NoMethodError if you call a method that doesn’t exist on an object.

a = Article.new

a.try(:author) #=> #<Author ...>

nil.try(:doesnt_exist) #=> nil

a.try(:doesnt_exist) #=> nil

Note:

a.try(&:doesnt_exist) #=> Raises NoMethodError
January 6, 2010
1 thank

Alternative:

without using at

[:a, :b, :c].try(:[], 1)
September 13, 2013
1 thank

Edge case

NilClass#try doesn’t check for methods on itself:

nil.blank?        #=> true
nil.try :blank?   #=> nil
February 3, 2015
0 thanks

Poor man's maybe

After creating a simple Maybe monad in Ruby, a colleaque noticed I could have just used try (I wasn’t aware try supports blocks). I think the method was even meant for such cases.

Why I mention this? Because it clarifies the whole ‘raises exception if method does not exist’ thing. It should not be crappy solution to exception handling, but allow for doing away with messy if statements. An example:

report = params[:query_type]
.try { |qt| build_query(qt) }
.try { |sql| run_query(sql) }
.try { |res| format_result(res) }

If any of the expressions params[], build_query, run_query etc. returns nil, the chain is halted and nil is returned. It still throws exceptions if a values is not nil and method does not exist, which is just like it should.