Differencebetween Using .Exists, and .Present? in Ruby

What is the difference between using .exists?, and .present? in Ruby?

To clarify: neither present? nor exists? are "pure" ruby—they're both from Rails-land.

present?

present? is an ActiveSupport extension to Object. It's usually used as a test for an object's general "falsiness". From the documentation:

An object is present if it’s not blank?. An object is blank if it’s false, empty, or a whitespace string.

So, for example:

[ "", " ", false, nil, [], {} ].any?(&:present?)
# => false

exists?

exists? is from ActiveResource. From its documentation:

Asserts the existence of a resource, returning true if the resource is found.

Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
Note.exists?(1) # => true

Differences between `any?` and `exists?` in Ruby on Rails?

#any and #exists? are very different beasts but query similarly.

Mainly, #any? accepts a block — and with this block it retrieves the records in the relation, calls #to_a, calls the block, and then hits it with Enumerable#any?. Without a block, it's the equivalent to !empty? and counts the records of the relation.

#exists? always queries the database and never relies on preloaded records, and sets a LIMIT of 1. It's much more performant vs #any?. #exists? also accepts an options param as conditions to apply as you can see in the docs.

What is the difference between using Active Record exists? versus find_by?

Rails wraps each controller action with a simple query cache. The CACHE in the logs does indicates that the query was served from the cache. If you were to run that code in the console you wouldn't get that caching (unless you explicitly set that up).

The difference query wise is that none of the fields of the object are fetched from the database. Aside from the network impact, depending on the query and the indices present, your database may be able to use a covering index (in a nutshell the index can be used to answer the query completely instead of the db using the index to find the data for the row)

On top of that rails doesn't construct an active record object from the result, you just get back true/false.

So exists? is faster. However it's pointless if you then call find_by straight after. You might as well call find_by once only.

What is the purpose of nil? and exists? methods in ruby/rails conditions?

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)

Rails active record querying association with 'exists'

You can use includes and then test if the related response(s) exists like this:

def surveys_completed
members.includes(:responses).where('responses.id IS NOT NULL')
end

Here is an alternative, with joins:

def surveys_completed
members.joins(:responses)
end

The solution using Rails 4:

def surveys_completed
members.includes(:responses).where.not(responses: { id: nil })
end

Alternative solution using activerecord_where_assoc:
This gem does exactly what is asked here: use EXISTS to to do a condition.
It works with Rails 4.1 to the most recent.

members.where_assoc_exists(:responses)

It can also do much more!


Similar questions:

  • How to query a model based on attribute of another model which belongs to the first model?
  • association named not found perhaps misspelled issue in rails association
  • Rails 3, has_one / has_many with lambda condition
  • Rails 4 scope to find parents with no children
  • Join multiple tables with active records

What is the best way to check if an attribute exists and is set?

You could use presence:

= link_to @element.title, (@element.link.presence || @element)

Or, if @element might not have link at all, you could use try:

= link_to @element.title, (@element.try(:link) || @element)

Check if record exists from controller in Rails

Why your code does not work?

The where method returns an ActiveRecord::Relation object (acts like an array which contains the results of the where), it can be empty but it will never be nil.

Business.where(id: -1) 
#=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
#=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
#=> returns true


How to test if at least one record exists?

Option 1: Using .exists?

if Business.exists?(user_id: current_user.id)
# same as Business.where(user_id: current_user.id).exists?
# ...
else
# ...
end

Option 2: Using .present? (or .blank?, the opposite of .present?)

if Business.where(:user_id => current_user.id).present?
# less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
# ...
end

Option 3: Variable assignment in the if statement

if business = Business.where(:user_id => current_user.id).first
business.do_some_stuff
else
# do something else
end

This option can be considered a code smell by some linters (Rubocop for example).

Option 3b: Variable assignment

business = Business.where(user_id: current_user.id).first
if business
# ...
else
# ...
end

You can also use .find_by_user_id(current_user.id) instead of .where(...).first


Best option:

  • If you don't use the Business object(s): Option 1
  • If you need to use the Business object(s): Option 3

How to return true if string exists in table, Ruby on Rails

You can check whether Robert exists or not by using .where().present

if @my_friends.where(:friend_id => 'Robert').present?
# Robert exists
else
# Robert doesn't exist
end

See this answer for more ways to check if a record exists.

How to check if a value exists in an array in Ruby

You're looking for include?:

>> ['Cat', 'Dog', 'Bird'].include? 'Dog'
=> true


Related Topics



Leave a reply



Submit