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 notblank?
. An object isblank
if it’sfalse
, 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
Ruby Hash Default Value Behavior
Strange Inability to Require Config/Boot After Upgrading to Ruby 1.9.2
Why Can't Singleton Methods Be Defined on Symbols or Fixnums
How to Check a Word Is Already All Uppercase
Unexpected Output in Ruby on Rails
How (Replace|Create) an Enum Field on Rails 2.0 Migrations
Ruby String to Date Conversion
Active Record - Find Records Which Were Created_At Before Today
Why Does My Ruby 'Ri' Tool Not Return Results in Command Prompt
Using Join Tables in Ruby on Rails
Colon (:) Appears as Forward Slash (/) When Creating File Name
How to Automate Chrome Request Blocking Using Selenium-Webdriver for Ruby
Looping Through an Array with Step
Can You Eval Code in the Context of a Caller in Ruby