'Check if record does NOT exist in Rails (from array of ids)?
I can do this to check if a record(s) exists (say id "1" exists, but "2" and "3" don't):
Model.exists?(:id => [1, 2, 3]) #=> true
How do I do the opposite, so:
Model.not_exists?(:id => [1, 2, 3]) #=> true
Solution 1:[1]
If you only need search records through ID you can try this
class Model
def self.not_exists?(ids)
self.find(ids)
false
rescue
true
end
end
If any of the IDs does not exist the find method will raise a ActiveRecord::RecordNotFound exception that we simply catch and return true.
Excuse my English :)
Solution 2:[2]
just add a ! operator
!Model.exists?(:id => [1, 2, 3]) #=> true
Solution 3:[3]
Use empty?, this is what you want. It uses count(*) vs select 1 as one.
> Rocketeer.where(:id => [1, 2, 3]).empty?
(0.6ms) SELECT COUNT(*) FROM "rocketeers" WHERE "rocketeers"."id" IN (1, 2, 3)
=> false
> Rocketeer.where(:id => [1, 2, 3]).any?
(0.5ms) SELECT COUNT(*) FROM "rocketeers" WHERE "rocketeers"."id" IN (1, 2, 3)
=> true
> Rocketeer.where(:id => [1, 2, 3]).exists?
Rocketeer Exists (0.5ms) SELECT 1 AS one FROM "rocketeers" WHERE "rocketeers"."id" IN (1, 2, 3) LIMIT 1
=> true
Solution 4:[4]
class Model
def self.does_not_exist?(ids)
Model.where(id: ids).count < ids.size
end
end
Explanation: If (and only if) all the instances you're looking for exist, Model.where(id: ids).count is equal to ids.size.
However if there are one or more instances missing, the count will be lower, meaning that there's a record that does not exist.
Solution 5:[5]
A more Ruby-esque way of doing it would be to use unless with exists?. This way, you don't have to use !. I imagine your use case is something like this:
def my_method
return unless Model.exists?(:id => [1, 2, 3])
# do something
end
You can replace 1, 2, 3 with a variable (call it id or something) and even remove the array altogether if you'd like: .exists?(id: id)
Solution 6:[6]
Another simple way is to use the where method with an array of id's.
# If the count of the query is equal to the count of all of the id's then the statement will return false.
# Else it will return true if not all ids exists in the database.
Model.where(id: [1, 2, 3]).count < [1,2,3].count
Solution 7:[7]
To ensure all ids exist, not just one the following works without have to rescue
ids = [1,2,3]
Model.where(id: ids).count != ids.length
The exists? method will return true if any of the ids match. The above will ensure all ids exist.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | afgomez |
| Solution 2 | GSto |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | Sticky |
| Solution 6 | |
| Solution 7 | surgentt |
