RAILS:具有现有记录的新方法中的嵌套属性

Src*_*Src 6 ruby-on-rails ruby-on-rails-5

我有模特:

Frame.rb

belongs_to :manufacturer, foreign_key: 'model'
accepts_nested_attributes_for :manufacturer, :reject_if => proc { |obj| obj.blank? }
Run Code Online (Sandbox Code Playgroud)

当我尝试使用现有制造商创建新框架时,我收到错误:

Frame.new({name: 'Name of the frame', manufacturer_attributes: {id:2}})
Run Code Online (Sandbox Code Playgroud)

错误:

Couldn't find Manufacturer with ID=2 for Frame with ID=
Run Code Online (Sandbox Code Playgroud)

nmo*_*ott 9

如果您想要一个现有制造商的新框架,您需要在参数中分配它以及使用嵌套属性。

Frame.new({name: 'Name', manufacturer_ids: [2], manufacturer_attributes: {id:2}})
Run Code Online (Sandbox Code Playgroud)

新框架现在具有指定的制造商,因此当它尝试使用它更新制造商时,manufacturer_attributes它可以正确找到它。

如果您只想分配现有制造商而不更新任何属性,那么您不需要manufacturer_attributes.


Jan*_*eck 6

的问题是,Frame.new为一个新的记录,当ActiveRecord的到达参数manufacturers_attributes它执行所述关联的查找manufacturers_attributes对于Frame.new其是未保存,因此没有ID与要执行查找.

我建议从现有manufacturer记录开始,然后简单地创建框架manufacturer.frames.create(frame_params)(假设一对多的关系).

但是,如果你必须这样做,你可以覆盖这样的manufacturer_attributes方法:

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

因此,您可以在原始程序manufacturer_attributes尝试在新记录上访问它之前分配制造商,而此记录之前会导致错误.