RAILS: Nested attributes in new method with existing record
Asked Answered
S

2

11

I have models:

Frame.rb

belongs_to :manufacturer, foreign_key: 'model'
accepts_nested_attributes_for :manufacturer, :reject_if => proc { |obj| obj.blank? }

When i try to create new Frame with existing manufacturer i get an error:

Frame.new({name: 'Name of the frame', manufacturer_attributes: {id:2}})

Error:

Couldn't find Manufacturer with ID=2 for Frame with ID=
Stuffing answered 20/5, 2016 at 21:14 Comment(4)
Does the manufacturer with an id of 2 exist?Exiguous
Just try commenting out :reject_if => proc { |obj| obj.blank? } part of the accepts_nested_attributesExiguous
@dane, It makes no sens but i already did thatStuffing
@Stuffing please provide result for Manufacturer.where(id: 2)Auraaural
L
12

The problem is that Frame.new is a new record, when ActiveRecord reaches the parameter manufacturers_attributes it performs a lookup on the association manufacturers_attributes for Frame.new which is unsaved and hence has no id with which to perform the lookup.

I recommend starting with the existing manufacturer record and simply create the frame like so manufacturer.frames.create(frame_params) (assuming a one-to-many relationship).

However, if you must do it this way you can overwrite the manufacturer_attributes method like so:

accepts_nested_attributes_for :manufacturer
  def manufacturer_attributes=(attributes)
    if attributes['id'].present?
      self.manufacturer = Manufacturer.find(attributes['id'])
    end
    super
  end

Thus, you assign the manufacturer before the original manufacturer_attributes tries to access it on the new record, which previously caused the error.

Leftward answered 20/5, 2016 at 21:55 Comment(1)
What if you have multiple manufacturer attributes some existing and some not?Pyrrhonism
G
9

If you want a new Frame with an existing manufacturer you need to assign it in the params as well as using nested attributes.

Frame.new({name: 'Name', manufacturer_ids: [2], manufacturer_attributes: {id:2}})

The new Frame now has the assigned Manufacturer so when it attempts to update the Manufacturer with the manufacturer_attributes it can find it correctly.

If you only want to assign the existing Manufacturer and not update any attributes then you don't need the manufacturer_attributes.

Godinez answered 21/9, 2016 at 1:34 Comment(1)
This works fine and is the right answer really, except manufacturer_attributes is not even needed. If you aren't attempting to create new associated records and specifically only want to create a parent pre-associated with existing other records, all you need is manufacturer_ids and do not need to accept-nested-attributes-for.Viscardi

© 2022 - 2024 — McMap. All rights reserved.