What is the point of object.presence?

Ruby on-RailsRuby

Ruby on-Rails Problem Overview


In the Rails docs, the example provided for the object.presence method is:

region = params[:state].presence || params[:country].presence || 'US'

But isn't that just equivalent to:

region = params[:state] || params[:country] || 'US'

What is the point of using presence?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Here's the point:

''.presence
# => nil

so if params[:state] == '':

region = params[:state].presence || 'US'
# => 'US'
region = params[:state] || 'US'
# => ''

What's more, it works in similar way (that is, returns nil if object is 'empty') on every object that responds to empty? method, for example:

[].presence
# => nil

Here's the documentation, for reference:

http://api.rubyonrails.org/classes/Object.html#method-i-presence

Solution 2 - Ruby on-Rails

The real point of using #presence is that it expands the notion of falsey values to handle web and http scenarios. The docs don't make this purpose clear ... instead simply focussing on the method's API: The what but not the why. Web and HTTP is different from normal programming because a blank string is often what you get instead of a nil from a request.

In plain Ruby, however, an empty string is truthy. This makes web developers write a lot of redundant boilerplate code like the docs for Object.presence uses as its example, as others here have quoted.

The bottom line for people writing web applications in Rails is that we can (should) now use #present? and #presence with the standard Ruby short-circuiting or, ||:

# Check for a param like this
@name = params[:name].presence || 'No name given'

That line properly handles everything the web server packs into the request params for us. While this plain old ruby does not:

# DON'T DO THIS
@name = params[:name] || 'No name given'

Solution 3 - Ruby on-Rails

presence is very useful when you want to return nil if object is not present and the object itself if the object is present. In other words you want a code that looks like this:

object.present? object : nil

Instead of the line above you can simply call object.presence and the method will do the work for you.

Solution 4 - Ruby on-Rails

As another example, presence lets me present my favorite FizzBuzz solution:

puts 1.upto(100).map { |n| "#{'Fizz' if n%3==0}#{'Buzz' if n%5==0}".presence || n }

Solution 5 - Ruby on-Rails

I just used it in a useful way I found neat. My variable is a string, if it's the empty string i want nil, otherwise I want it converted to an integer.

 x.presence.try(&:to_i)

 "".presence.try(&:to_i) # => nil
 "22".presence.try(&:to_i) # => 22

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbenView Question on Stackoverflow
Solution 1 - Ruby on-RailsMarek LipkaView Answer on Stackoverflow
Solution 2 - Ruby on-RailsDogweatherView Answer on Stackoverflow
Solution 3 - Ruby on-RailsradoAngelovView Answer on Stackoverflow
Solution 4 - Ruby on-RailsDan KohnView Answer on Stackoverflow
Solution 5 - Ruby on-RailsjrochkindView Answer on Stackoverflow