Accepts_nested_attributes_for, reject_if and has_one relationships don't work together?

In my model I have

has_one :order, dependent: :destroy accepts_nested_attributes_for :order, reject_if: lambda { |order| order[:description].blank? }, allow_destroy: true 

For some reason, although reject_if is checked and returns true (I checked this with the debugger), the nested order is not destroyed.

There is a lot of talk about this phenomenon on the Internet, but I cannot find a solution.

Does anyone know how to solve this?

+6
source share
3 answers

Finally, I created an intelligent "reject_if" to set the destruction flag in this particular case, as described in "Destroy by an empty nested attribute" , but, according to my own standards, this is not a very "ruby", so I can’t imagine that there is no better solution ...

 accepts_nested_attributes_for :order, allow_destroy: true, reject_if: lambda { |attributes| exists = attributes['id'].present? empty = attributes[:description].blank? attributes.merge!({_destroy: 1}) if exists and empty return (!exists and empty) } 
+2
source

From nested_attributes API

You can also set: reject_if proc to silently ignore any new hashes of the record if they cannot pass your criteria.

 params = { member: { name: 'joe', order_attributes: [ { description: 'Kari, the awesome Ruby documentation browser!' }, { description: 'The egalitarian assumption of the modern citizen' }, { description: '', _destroy: '1' } # this will be ignored ] }} 

Any hash with a description space will be completely ignored, even if it has the _destroy flag.

If you want to delete entries with a blank description, I can think of two solutions

Option 1: delete them with a callback in your model:

 before_save :remove_orders_without_description def remove_orders_without_description orders.select{|o| o.description.blank?}.each(&:delete) end 

Option 2: remove the reject_if parameter in the model definition and use JS in the view to set the _delete attribute _delete

+1
source

try it

 accepts_nested_attributes_for :order, reject_if: lambda { |order| order[:_destroy].blank? && order[:description].blank? }, allow_destroy: true 
0
source

All Articles