How to select where ID in Array Rails ActiveRecord without exception

Ruby on-RailsActiverecordFind

Ruby on-Rails Problem Overview


When I have array of ids, like

ids = [2,3,5]

and I perform

Comment.find(ids)

everything works fine. But when there is id that doesn't exist, I get an exception. This occurs generaly when I get list of IDs that match some filter and than I do something like

current_user.comments.find(ids)

This time I may have a valid comment ID, which however does not belong to given User, so it is not found and I get an exception.

I've tried find(:all, ids), but it returns all of the records.

The only way I can do it now is

current_user.comments.select { |c| ids.include?(c.id) }

But that seems to me like super inefficient solution.

Is there better way to select ID in Array without getting exception on non-existing record?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

If it is just avoiding the exception you are worried about, the "find_all_by.." family of functions works without throwing exceptions.

Comment.find_all_by_id([2, 3, 5])

will work even if some of the ids don't exist. This works in the

user.comments.find_all_by_id(potentially_nonexistent_ids)

case as well.

Update: Rails 4
Comment.where(id: [2, 3, 5])

Solution 2 - Ruby on-Rails

Update: This answer is more relevant for Rails 4.x

Do this:

current_user.comments.where(:id=>[123,"456","Michael Jackson"])

The stronger side of this approach is that it returns a Relation object, to which you can join more .where clauses, .limit clauses, etc., which is very helpful. It also allows non-existent IDs without throwing exceptions.

The newer Ruby syntax would be:

current_user.comments.where(id: [123, "456", "Michael Jackson"])

Solution 3 - Ruby on-Rails

If you need more control (perhaps you need to state the table name) you can also do the following:

Model.joins(:another_model_table_name)
  .where('another_model_table_name.id IN (?)', your_id_array)

Solution 4 - Ruby on-Rails

Now .find and .find_by_id methods are deprecated in rails 4. So instead we can use below:

Comment.where(id: [2, 3, 5])

It will work even if some of the ids don't exist. This works in the

user.comments.where(id: avoided_ids_array)

Also for excluding ID's

Comment.where.not(id: [2, 3, 5])

Solution 5 - Ruby on-Rails

To avoid exceptions killing your app you should catch those exceptions and treat them the way you wish, defining the behavior for you app on those situations where the id is not found.

begin
  current_user.comments.find(ids)
rescue
  #do something in case of exception found
end

Here's more info on exceptions in ruby.

Solution 6 - Ruby on-Rails

You can also use it in named_scope if You want to put there others conditions

for example include some other model:

> named_scope 'get_by_ids', lambda { |ids| { :include => [:comments], :conditions => ["comments.id IN (?)", ids] } }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJakub ArnoldView Question on Stackoverflow
Solution 1 - Ruby on-RailsprismofeverythingView Answer on Stackoverflow
Solution 2 - Ruby on-RailsmjnissimView Answer on Stackoverflow
Solution 3 - Ruby on-RailsJonathan LinView Answer on Stackoverflow
Solution 4 - Ruby on-RailsSumit MunotView Answer on Stackoverflow
Solution 5 - Ruby on-RailsrogeriopvlView Answer on Stackoverflow
Solution 6 - Ruby on-RailsmtfkView Answer on Stackoverflow