0

I often (very often) see code like this in the conditions:

<% catalog.each do |article| %>
  <% if article.image.nil? %>
    ...

or (e.g. seen there)

<% catalog.each do |article| %>
  <% if article.image.exists? %>
    ...

However we all know that nil interprets like false in the conditions. ActiveRecord query returns nil if nothing found.

Why not simply write:

<% unless article.image %> (unless there is article do something)

instead of

<% if article.image.nil? %> (if there is nothing at article.image do something)

and

<% if article.image %> instead of <% if article.image.exists? %>

I usually write the code without nil? and exists?. What am I missing? Is there any pitfalls?

1
  • 1
    as a note nil? and exists? are very different. exists? is a rails query method and can have additional conditions passed to it similar to where query conditions. Also the query created is very different as well exists? will generate a query like SELECT 1 FROM table_name WHERE conditions rather than SELECT * FROM table_name WHERE conditions this can be far more efficient when the record actually exists because it does not actually create an ActiveRecord object but rather just returns true or false. Commented Aug 8, 2016 at 18:06

3 Answers 3

3

In your example, and in many typical RESTful Rails patterns, you're correct that using the implicit version is identical in behavior.

But there are certainly suations where nil? and exists? are necessary and/or more readable...

For instance, nil? is the only option when you're reading a boolean attribute, and you need different behavior for false vs nil (since both are falsey in Ruby).

Or, assume in your example, that each Article has many images, and you define a method to get an Article's first image according to display order:

def primary_image
  images.order(display_order: "ASC").limit(1)
end

In this case, if your Article doesn't have any images, primary_image will return an empty collection, which is truthy. So, in this case, you'd need to use exists? (or present?). Rails provides several convenience methods for checking data records.

(or make sure the primary_image method returns nil or false when the collection is empty)

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

3 Comments

Thank you for a good explanation! Rails also has some methods to check whether collection is empty or not. I mean blank? and present?
You're correct @user1201917, thanks for pointing that out (I updated the answer)
Another note...I purposely used limit(1), in my example, because it returns an empty collection if no records are found. However, the more appropriate first method actually returns nil if no record is found, which would end up being the correct implicit behavior anyway. Further supports that most patterns work just fine with implicit checks.
1

Personally, I rarely use either one of them. Like you suggested, I mostly just use if or unless depends on the situation without bothering with nil? or exists?

As for the difference between the two:

nil? is a Ruby method to see whether the object is nil or not.

exists? is a Rails method to see whether the record exists in the database

I guess, just use whichever is more efficient. I have been trying to convert my codes to use try to avoid no method error.

1 Comment

Thank you for answer. I use try to avoid no method error too.
1

Most of the time it's just to be more explicit I suppose.

In your example above it doesn't matter if you check explicitly or implicitly.

But if you want to check explicitly for nil for example, you use the #nil? because sometimes you want to react differently if false is returned.

As an example: false and nil are often not interchangeable for boolean values in a database.

Like @lusketeer already said is nil? a method of the ruby standard library and exists? a method of the Rails framework.

But I think almost always you are good with the implicit way.

1 Comment

Thanks! You dispelled my doubts about implicity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.