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
?
Use of the #presence method provides a very convenient shortcut to return either the object (if it exists) or nil . It is the equivalent of writing object. present? ? object : nil , which is a pattern you often see in views in Rails where data may or may not exist.
presence() public. Returns the receiver if it's present otherwise returns nil. object.presence is equivalent to object.
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
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'
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.
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 }
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With