rubyguides

Object#try

Object#try is an ActiveSupport extension that calls a method on an object only if the object responds to it. If the object does not respond to the method, it returns nil instead of raising a NoMethodError. This is particularly useful when working with objects that may or may not have certain methods, or when chaining method calls on objects that could be nil.

The method is mostly about keeping conditional logic out of the call site. Instead of checking for nil or respond_to? by hand, you can let try do that guard for you and keep the chain readable.

Intro context

try comes from ActiveSupport, so it shows up most often in Rails code. It is not part of core Ruby, which means the tradeoff is a little different from a plain language method: you get convenience, but only inside an environment that loads the extension.

Signature

ParameterTypeDescription
method_nameSymbol or StringThe name of the method to call
*argsArrayArguments to pass to the method
&blockBlockA block to pass to the method

Code examples

# Basic usage - call method if it exists
user = User.new(name: "John")
user.try(:name)           # => "John"
user.try(:email)          # => nil (method does not exist)

# With arguments
user.try(:format_name, :uppercase)

# With a block
user.try(:names) { |n| n.upcase }

# Safe navigation alternative
# Instead of: @user && @user.profile && @user.profile.name
@user.try(:profile).try(:name)

That style is handy when the chain is optional, but it is worth remembering that each call can hide a missing method. The result is convenient, but it can also make it slightly harder to spot typos or unexpected object shapes.

Practical example

# nil-safe chaining through multiple objects
def user_city(user)
  user.try(:address).try(:city) || "Unknown"
end

alice = OpenStruct.new(address: OpenStruct.new(city: "Seattle"))
bob = OpenStruct.new(address: nil)

user_city(alice)  # => "Seattle"
user_city(bob)    # => "Unknown"

# Without try, you would write:
# user && user.address && user.address.city || "Unknown"

Here try eliminates the repeated && guards, keeping the chain readable without burying the intent inside branching logic. The fallback to "Unknown" at the end makes the whole expression safe even when every intermediate object is nil.

Common use cases

  1. Handling potentially nil objects: Avoid explicit nil checks when calling methods on objects that might be nil.

  2. Working with dynamic attributes: Call methods that may or may not exist based on the object class or configuration.

  3. Chained method calls: Safely navigate through nested associations where intermediate objects might be nil.

Those cases all share the same pattern: the code is more concerned with “if this exists, use it” than with raising an immediate error. That makes try a good fit for view code, optional associations, and soft integrations.

Edge cases and gotchas

  • Calling try on nil always returns nil — this is the main feature, not a bug.

  • Private methods: By default, try does not call private methods. Use try! or pass the method as a string to access private methods in some cases.

  • NoMethodError vs nil: If you want an error to be raised when the method does not exist, use try! instead.

  • Performance: try uses respond_to? internally, so there is a slight overhead compared to direct method calls.

The performance cost is small, but it is still a real cost. If the code path is hot or the method is expected to exist every time, a direct call is usually simpler and faster.

Return Value

Returns the result of the method call if the object responds to the method, otherwise returns nil.

In practice, that means try is best when a missing method should be treated as “nothing to do” rather than a hard failure. If you need a stricter contract, public_send or a plain call is often the better choice.

See Also

  • Object#tap — useful when you want to keep chaining while inspecting an object
  • Object#present? — returns the object if it is present, nil otherwise
  • Object#dig — safely extract nested values from hashes and arrays