Rails 嵌套属性和不断变化的关联
Rails nested attributes and changing associations
这个让我难住了一整天!
我有以下型号:
暴涨class
class Pump < ApplicationRecord
has_one :control, as: :equipment
accepts_nested_attributes_for :control
泵模式
class CreatePumps < ActiveRecord::Migration[5.1]
def change
create_table :pumps do |t|
t.references :property, foreign_key: true, null: false
t.string :name, default: 'Pump', null: false
t.timestamps
end
end
end
控制class
class Control < ApplicationRecord
belongs_to :equipment, polymorphic: true
控制模式
class CreateControls < ActiveRecord::Migration[5.1]
def change
create_table :controls do |t|
t.belongs_to :device, foreign_key: true, index: true
t.integer :position, index: true
t.references :equipment, polymorphic: true, index: true
t.belongs_to :control_type, foreign_key: true, index: true
t.timestamps
end
end
end
我正在尝试更新 Control 和 Pump 之间的关联。以下作品:
[439] pry(main)> Pump.first.update!(control: Control.find(62))
.
.
.
=> true
但是下面的不是,我不明白为什么。
[438] pry(main)> Pump.first.update(control_attributes: {id: 62})
(0.4ms) BEGIN
(0.4ms) ROLLBACK
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump
with ID=1
from /usr/local/bundle/gems/activerecord-
5.1.5/lib/active_record/nested_attributes.rb:584:in
`raise_nested_attributes_record_not_found!'
上下文是我有一个 Pump 表单,在编辑我的 Pump 时,select 下拉列表中有一个控件列表。我只想选择与泵关联的控件。
更新1:回答下面的问题
[468] pry(main)> Pump.first.update(control_attributes: {id: 62})
Pump Load (1.0ms) SELECT "pumps".* FROM "pumps" ORDER BY "pumps"."id" ASC LIMIT [["LIMIT", 1]]
(0.3ms) BEGIN
Control Load (0.4ms) SELECT "controls".* FROM "controls" WHERE "controls"."equipment_id" = AND "controls"."equipment_type" = LIMIT [["equipment_id", 1], ["equipment_type", "Pump"], ["LIMIT", 1]]
(0.3ms) ROLLBACK
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump with ID=1
from /usr/local/bundle/gems/activerecord-5.1.5/lib/active_record/nested_attributes.rb:584:in `raise_nested_attributes_record_not_found!'
当您对链接模型使用 accepts_nested_attributes_for
时,如果提供的属性没有 id
参数,它将创建新记录。当属性提供 id
参数时,它将更新与父记录链接的现有记录。
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump
with ID=1
:此错误表明没有找到具有上述 ID 的 Pump
对象的 Control
记录。
您可以为泵添加新的控制记录:
Pump.first.update(control_attributes: { attribute1: 'attribute1_value' } )
这将创建与 ID 为 1
的 Pump
对象关联的新 Control
记录。现在您可以按如下方式再次更新:
Pump.first.update(control_attributes: { id: 1, attribute1: 'updated_attribute1_value' } )
注意新创建的Control记录的id
取为1
.
请阅读 through the documentation 了解更多详情。
希望对您有所帮助!
Pump.first.update(control_attributes: {id: 62})
Rails的嵌套属性不是这样用的!上面的代码表示:
找一个id为62的控件,它的equipment_type应该是"Pump",它的equipment_id应该是Pump.first.id,然后更新为extra 参数,你没有提供。
您出现此错误是因为在第一步中,id 为 62 的控件 equipment_id 不是 Pump.first.id
例如,要更新 ID 为 60 的控件的名称,属于 Pump.first,正确关联:
Pump.first.update(control_attributes: {id: 60, name: "xxxx"})
您可以覆盖模型中的嵌套属性 setter 方法,这样它也可以直接更新外键列。
# pump.rb
def control_attributes=(attributes)
if (new_control = Control.find_by(id: attributes[:id]))
self.control_id = new_control.id
end
super
end
注意:直接分配关系时要小心(即 self.control = new_control
),因为如果它是用 :dependent
选项定义的 has_one 关联,这可能会导致一些意想不到的副作用这会导致删除记录。
这个让我难住了一整天!
我有以下型号:
暴涨class
class Pump < ApplicationRecord
has_one :control, as: :equipment
accepts_nested_attributes_for :control
泵模式
class CreatePumps < ActiveRecord::Migration[5.1]
def change
create_table :pumps do |t|
t.references :property, foreign_key: true, null: false
t.string :name, default: 'Pump', null: false
t.timestamps
end
end
end
控制class
class Control < ApplicationRecord
belongs_to :equipment, polymorphic: true
控制模式
class CreateControls < ActiveRecord::Migration[5.1]
def change
create_table :controls do |t|
t.belongs_to :device, foreign_key: true, index: true
t.integer :position, index: true
t.references :equipment, polymorphic: true, index: true
t.belongs_to :control_type, foreign_key: true, index: true
t.timestamps
end
end
end
我正在尝试更新 Control 和 Pump 之间的关联。以下作品:
[439] pry(main)> Pump.first.update!(control: Control.find(62))
.
.
.
=> true
但是下面的不是,我不明白为什么。
[438] pry(main)> Pump.first.update(control_attributes: {id: 62})
(0.4ms) BEGIN
(0.4ms) ROLLBACK
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump
with ID=1
from /usr/local/bundle/gems/activerecord-
5.1.5/lib/active_record/nested_attributes.rb:584:in
`raise_nested_attributes_record_not_found!'
上下文是我有一个 Pump 表单,在编辑我的 Pump 时,select 下拉列表中有一个控件列表。我只想选择与泵关联的控件。
更新1:回答下面的问题
[468] pry(main)> Pump.first.update(control_attributes: {id: 62})
Pump Load (1.0ms) SELECT "pumps".* FROM "pumps" ORDER BY "pumps"."id" ASC LIMIT [["LIMIT", 1]]
(0.3ms) BEGIN
Control Load (0.4ms) SELECT "controls".* FROM "controls" WHERE "controls"."equipment_id" = AND "controls"."equipment_type" = LIMIT [["equipment_id", 1], ["equipment_type", "Pump"], ["LIMIT", 1]]
(0.3ms) ROLLBACK
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump with ID=1
from /usr/local/bundle/gems/activerecord-5.1.5/lib/active_record/nested_attributes.rb:584:in `raise_nested_attributes_record_not_found!'
当您对链接模型使用 accepts_nested_attributes_for
时,如果提供的属性没有 id
参数,它将创建新记录。当属性提供 id
参数时,它将更新与父记录链接的现有记录。
ActiveRecord::RecordNotFound: Couldn't find Control with ID=62 for Pump
with ID=1
:此错误表明没有找到具有上述 ID 的 Pump
对象的 Control
记录。
您可以为泵添加新的控制记录:
Pump.first.update(control_attributes: { attribute1: 'attribute1_value' } )
这将创建与 ID 为 1
的 Pump
对象关联的新 Control
记录。现在您可以按如下方式再次更新:
Pump.first.update(control_attributes: { id: 1, attribute1: 'updated_attribute1_value' } )
注意新创建的Control记录的id
取为1
.
请阅读 through the documentation 了解更多详情。
希望对您有所帮助!
Pump.first.update(control_attributes: {id: 62})
Rails的嵌套属性不是这样用的!上面的代码表示:
找一个id为62的控件,它的equipment_type应该是"Pump",它的equipment_id应该是Pump.first.id,然后更新为extra 参数,你没有提供。
您出现此错误是因为在第一步中,id 为 62 的控件 equipment_id 不是 Pump.first.id
例如,要更新 ID 为 60 的控件的名称,属于 Pump.first,正确关联:
Pump.first.update(control_attributes: {id: 60, name: "xxxx"})
您可以覆盖模型中的嵌套属性 setter 方法,这样它也可以直接更新外键列。
# pump.rb
def control_attributes=(attributes)
if (new_control = Control.find_by(id: attributes[:id]))
self.control_id = new_control.id
end
super
end
注意:直接分配关系时要小心(即 self.control = new_control
),因为如果它是用 :dependent
选项定义的 has_one 关联,这可能会导致一些意想不到的副作用这会导致删除记录。