15

In Ruby on Rails, is there a difference between:

if obj
  # ...
end

and:

if obj.present?
  # ...
end

It seems they do the same thing and not using .present? would help keep the line of code shorter and potentially cleaner. I understand that .present? is the opposite of blank? but should we always be using it when trying to determine if an object is "truthy" or not?

Is there a performance difference of some kind?

3
  • 1
    Possible duplicate of A concise explanation of nil v. empty v. blank in Ruby on Rails Commented Aug 6, 2019 at 14:41
  • Maybe, but I don't really need to know the difference between nil, empty, blank, present. I'm simply asking if it's worth calling .present? on an object when testing for truthiness. Commented Aug 6, 2019 at 14:51
  • There is a performance cost to present? since adds a additional layer of calls, wether or not its significant is something you can test with a benchmark. But I do find that Rails noobs use it far too much - especially in cases where you are just checking if a variable is defined (not nil). Commented Aug 6, 2019 at 16:29

3 Answers 3

14

The #present? method does a bit more in that it also returns false if the string was a real but empty string (i.e. "")

Which is useful as your forms might return empty strings instead of nils.

You can also use #presence which is a useful way of returning the value only if the value is #present?

name = params[:name].presence || 'ardavis'

The above wouldn't work if params[:name] was an empty string and you didn't use #presence

Sign up to request clarification or add additional context in comments.

5 Comments

But if I know my object is not a string then there's no real need for .present?, right? If I did obj = MyModel.find(some_id) then I know it's either nil or an instance of MyModel, right?
@ardavis find will never return nil (find_by will though). If find fails it will raise ActiveRecord::ResourceNotFound
Sorry, bad example. But yes, that's true.
Yes, if I'm doing my_model = MyModel.find_by(id: some_id) I pretty much never use my_model.present? so I agree with you there. Note that #present? also is useful (hoiwever) for empy arrays, empty hashes, and even ActiveRecord::Relation as in User.where(last_name: 'Moussolini').present?
Thanks, I appreciate your responses.
8

They don't do the same thing at all.

In Ruby everything except nil and false are truthy. This is amazingly sane compared to the type casting schenigans in other popular dynamic languages.

irb(main):003:0> !!""
(irb):3: warning: string literal in condition
=> true
irb(main):004:0> !!0
=> true
irb(main):005:0> !![]
=> true
irb(main):006:0> !!{}
=> true
irb(main):007:0> !!Object.new
=> true
irb(main):008:0> !!nil
=> false
irb(main):009:0> !!false
=> false

present? and presence are a part of ActiveSupport which can be used to test for nil and false but are actually more useful when dealing with user input:

irb(main):010:0> "".present?
=> false
irb(main):011:0> [].present?
=> false
irb(main):012:0> {}.present?
=> false

present? and presence are widely overused by Rails beginners that don't bother to learn Ruby first. Just use implicit truth checks (if foo) or foo.nil? if you just want to check if an argument is sent or not or if a variable is set.

And while .present? can be used on ActiveRecord collections but there are more idiomatically correct choices such as any? and none?.

Comments

1

If you are working with string only checking if the attribute or object exists will return true, but present method will return false.

Here are some examples:

# Double negation return the boolean value
!!""
=> true


"".present?
=> false

" ".present?
=> false

[].present?
=> false

nil.present?
=> false

true.present?
=> true

false.present?
=> false

{}.present?
=> false

person = {:firstName => "John", :lastName => "Doe"}
person.present?
=> true

5.present?
=> true

0.present?
=> true

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.