3

I am trying to find a model by an array of ids like so:

Model.find [1,2,3]

but let's say only two of these models exist (the model with id of 2 was deleted):

#<Model id: 1>
#<Model id: 3>

I get an error like this:

#<ActiveRecord::RecordNotFound: Couldn't find all Models with 'id': (1, 2, 3) (found 2 results, but was looking for 3).>

Is it possible to catch this error and determine which of the models were not present?

say i'm in my controller:

def index
  @models = Model.find params.require(:model_ids)
rescue ActiveRecord::RecordNotFound => e
  e.full_message
  ???
end

I'd like to, in the ??? line, run some code on the exception e that will return 2, letting me know what of the models was not found, so I can re-run the query without it while noting which ones weren't found.

5
  • 3
    Is it strictly mandatory to rescue in case a record with the given ids doesn't exist? Can't you use where and then check the difference by comparing the resulting ids with the given ones? Commented Apr 20, 2020 at 17:38
  • 1
    Using exceptions for control flow is usually not a good idea Commented Apr 20, 2020 at 17:43
  • @SebastianPalma that was my plan if this was not possible. I was just curious if it was even because it seems like somewhere in the error this is tracked, I just was unable to figure out where. Commented Apr 20, 2020 at 17:43
  • 1
    I think that'd be very handy, but kind of too much for ActiveRecord and considering exceptions for control flow isn't advised and/or expensive, at least in Ruby. Commented Apr 20, 2020 at 17:53
  • 1
    I'd encourage you to add an answer to your question since it involves a common doubt to the problem. I don't see why it should be closed. Commented Apr 20, 2020 at 17:54

1 Answer 1

7

Wrong method. .find should be used to find specific records when you want the code to raise ActiveRecord::RecordNotFound. This is done to ensure that the record exists and avoid nil errors. Typically this is used to trigger a 404 response without repeating the same boilerplate:

def show
  @record = Record.find_by(id: params[:id])
  unless @record
    render file: 'public/404.html', status: :not_found
  end
end

Use .find_by(id: id) if you don't want the code to raise.

To fetch multiple records use where:

models = Model.where(id: [1,2,3])

If you want to determine which of those ids don't exist use an array diff:

bad_ids = [1,2,3] - models.ids
Sign up to request clarification or add additional context in comments.

Comments

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.