Do not raise ActiveRecord::RecordNotFound if nested attributes marked for destruction do not exist

571 Views Asked by At

I'm using Rails nested attributes with allow_destroy: true. If I call something like this:

deck.update(deck_items_attributes: { id: 1000, _destroy: true })

and the deck_item with id 1000 does not exist Rails raise the exception ActiveRecord::RecordNotFound.

Is there any way to tell Rails not to throw the exception and just ignore that record?

3

There are 3 best solutions below

1
On

You can always use begin rescue to handle such type of exceptions like this

begin
  deck.update(deck_items_attributes: { id: 1000, _destroy: true })
rescue ActiveRecord::RecordNotFound => e
  puts custom_error_msg
end
2
On

Use the reject_if: option to drop the attributes hash if the record does not exist:

accepts_nested_attributes_for :deck_items,
   reject_if: :deck_item_does_not_exist?

private
def deck_item_does_not_exist?(attributes)
  if attributes["id"].present? && attributes["_destroy"].present? 
    DeckItem.where(id: attributes["id"]).none?
  else
    false
  end
end
0
On

I know this is old, but for anyone looking for a solution to the RecordNotFound exception when using nested_attributes, I ended overwriting the method that raises that exception in an initializer as follows:

module ActiveRecord
  module NestedAttributes
    def raise_nested_attributes_record_not_found(association_name, record_id)
    end
  end
end

Hope it helps!

Edit: This change is application wide. If you want a per model solution, you can overwrite the same method on your desired model.