Object#try from ActiveSupport is a code smell. What developers need in the vast majority of cases is &. or Object#try!.

What is the difference between those? x.try(:method) returns nil when x is a non-nil object that does not respond to :method. On the other hand, x&.method fails with NoMethodError in such cases.

Why is this difference important? It is important because of the reasons is outlined in the previous post about flatten. try is very vague. It declares that you don’t know what kind of object is the receiver. If you pass the wrong kind of object, for example something that does not respond to the passed message, try will just silently hide this from you. This is bad because it just postpones the error until later. It is always better to fail ASAP (at compile time, if you wish), than to delay the error and pretend that everything is fine.

Here is an example.

options[:namespace].try(:gsub, /\//, "_")

What happens there if someone passes {namespace: :core} instead of {namespace: 'core'}, perhaps because of a bug? The poor user will just get confused why :namespace param is ignored, and she will need to investigate the source code to understand what happens there.

On the other hand, if we use try! there, the code will rightfully blow up with a nice message:

def f(options = {})
  options[:namespace].try(:gsub, /\//, "_")

f()                  # => nil
f(namespace: 'core') # => 'core'
f(namespace: :core)  # => nil # what? why?

def g(options = {})
  options[:namespace].try!(:gsub, /\//, "_")

g()                  # => nil
g(namespace: 'core') # => 'core'
g(namespace: :core)  # => NoMethodError: undefined method `gsub' for :core:Symbol
                     # Immediately clear what went wrong.

There are many more examples like this:

# Are you claiming here that `User` instances may or may not respond
# to `:autnenticate`? Doesn't sound realistically. Maybe you are
# claiming that `find_by` can return something that is not `nil` or
# an instance of `User`? Also doesn't sound like truth. So why not
# use `try!` then? It's like documentation: you are essentially
# asserting that `find_by` returns either something that responds to
# `:authenticate` or `nil`.
User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe')

# What? Are there weird kind of exceptions that do not respond to
# `:message`? Unlikely so. Then don't use `try`. Use `&.` or `try!`.

Again, the difference between try! and try is the difference between confident code and sloppy code.

And by the way, try! is more performant than try on average.

There are cases when try is really needed, but they are rare.