Happy Monday!
all posts

Overview about nil?, blank?, present?, presence, try and other basic things

Published on Mar 13, 2014

Sven Pachnit GitHub Twitter StackOverflow

This is a post about basic things and if you are an experienced user you might want to skip this one but I see a lot of beginners and also advanced users which are not using them.

First you should know that Ruby only knows of two falsy values which are nil and false. Anything else is evaluated to true.

Secondly the "or" operator in Ruby || always returns one of the values you are comparing. In PHP for example $var = $foo || "bar" would result in $var being a boolean value but in Ruby it's much nicer! var = foo || "bar" would result in var being foo if it is not falsy or the last value in the chain. The following two lines are basically identical:

foo = a || b || c || "other"
foo = a ? a : b ? b : c ? c : "other"

If you're using || you might think can't I just use or since that reads nicer?. You can't. || isn't the same as or and && isn't the same as and in terms of precendence.

Consider using presenters (aka. decorators). They are really cool, even with these tricks.

nil?

I see beginners doing this:

link_to(user.job.nil? ? "Unemployed" : user.job, jobs_path)

Since nil is already falsy you could omit this explicit check. A string attribute in ActiveRecord only returns either nil or the string. Checking #nil? explicitely is rarely used and you wont see this very often. So get rid of it:

link_to(user.job ? user.job : "Unemployed", jobs_path)

But since we know how || works we could make it even shorter:

link_to(user.job || "Unemployed", jobs_path)

Cool eh?

blank? and present? (and presence)

Side note: blank? is the exact opposite of present? and all three methods are defined on Object so you can use them on any object (there are some exceptions but this is another topic).

What if the job is an empty string? This will happen by default when your form field is left empty. We'd had to check for job being present. So we'd end up again with something like this:

link_to(user.job.present? ? user.job : "Unemployed", jobs_path)

But fortunately there is presence which will return the object when it's present? or nil otherwise. So we can use || again:

link_to(user.job.presence || "Unemployed", jobs_path)
There is a handy gem called nilify_blanks which optionally set attributes to nil when they are blank.

try, try!

try is a really cool helper to remove conditional code. The functionality has changed in Rails/ActiveSupport 4 so if you are using v3 then your try behaves like try! in version 4.

Try calls a method on an object (like send) but only when it is truthy and returns the result. You can chain these together but keep the chain of responsibility in mind.

So from the above example assume that the job is a relation and has an attribue "name". We now need additional conditions:

link_to((user.job ? user.job.name.presence : nil) || "Unemployed", jobs_path)

But with try it's as easy as:

link_to(user.job.try(:name).presence || "Unemployed", jobs_path)

When there is no related job record user.job would be nil so try wouldn't call name on it and return nil instead.

With Rails 4 try also won't call the method if the object is truthy but doesn't respond to the method. If you don't want this use try!. Also take a look at the documentation.

"".try(:each) { "we never get here" }
"".try!(:each) # NoMethodError undefined method `each' for "":String

tap

This is a Ruby core method and functions like the meanwhile gone returning method from ActiveSupport. It just returns the object it is called on after calling the block passed to the tap method. It sometimes can be really handy but don't overuse it. In some cases it's not even necessary.

The reason why it is so useful is that ruby always passes references to objects around. So it can be useful when working with mutable objects (which are most types). You cannot however change the type of the variable.

It is also good for inject logging in chained method calls. Actually that is the intended , documented use for it which also has a good example.

Now an example for how it could be used with mutable objects:

def foo opts = {}
  result = []
  result << "foo" if opts[:foo]
  result << "bar" if opts[:bar]
  result
end

def foo opts = {}
  [].tap do |result|
    result << "foo" if opts[:foo]
    result << "bar" if opts[:bar]
  end
end

You can do this with strings, arrays, hashes and other objects on higher levels. Numeric values, symbols, nil or boolean values are not mutable and can't be changed in this manner. But note that many high level objects like the ActiveRecord model object are supporting this already:

Post.new do |p|
  p.foo = "bar"
  p.save!
end

@user.comments.build do |c|
  c.subject = "…"
  c.message = "…"
end