提问人:nmadoug 提问时间:5/27/2023 更新时间:5/29/2023 访问量:65
使用自加入关联更新 Rails 记录不会更新自加入列
Updating Rails record with self-join association doesn't update self join column
问:
对于我的班级,我有以下自加入协会:Employee
class Employee < ApplicationRecord
belongs_to :replaces_employee, class_name: "Employee", optional: true
has_one :replaced_by_employee,
class_name: 'Employee',
foreign_key: 'replaces_employee_id'
end
我的数据库表有列。employees
replaces_employee_id
在我的应用中,如果员工获得新角色,则会发生以下情况:
- 克隆当前员工记录。
<current record's>.replaces_employee
= 克隆的记录- 克隆的记录已保存。
- 保存当前员工记录以保留其他数据属性(即名称更改)。在保存过程中,Rails 神奇地用克隆的记录 ID 自动更新了当前记录的列。
replaces_employee_id
是的,这种魔力很棒,在我的旧 Rails 4.2 应用程序中有效。不幸的是,这不适用于我的 Rails 7.0 应用程序。我尝试使用显式外键更新关联,但无济于事。请注意,对于已填充的现有数据库记录,我可以访问关联的 AR(即 作品)。belongs_to
replaces_employee_id
Employee.find(1).replaces_employee
知道为什么这不适用于 Rails 7 吗?我缺少 4.2 端的一些配置吗?
答:
0赞
Alex
5/29/2023
#1
除此之外,rails 7 中没有方法,一切似乎都有效:update_attributes!
# app/models/employee.rb
class Employee < ApplicationRecord
belongs_to :replaces_employee, class_name: "Employee", optional: true
has_one :replaced_by_employee, class_name: "Employee", foreign_key: "replaces_employee_id"
def replace
# how deep is deep clone? did you check for validation errors?
other = deep_clone
other.attributes = {name: "copy of #{name}"}
# call `save!` or `update!` to raise validation errors
# when you call `save` or `update` you need to check for `errors`
# employee.save
# employee.errors #=> ???
update!({name: "new name",
replaces_employee: other})
end
end
>> Employee.create!
=> #<Employee:0x00007eff8c5cc5a0 id: 1, name: nil, replaces_employee_id: nil>
>> Employee.first.replace
=> true
>> Employee.all
=>
[#<Employee:0x00007eff7e4e08c0 id: 1, name: "replaced name", replaces_employee_id: 2>,
#<Employee:0x00007eff7e4e0780 id: 2, name: "copy of ", replaces_employee_id: nil>]
>> 3.times { Employee.first.replace }
=> 3
# i just dont' know if that's how you expect this to work
>> Employee.all
=>
[#<Employee:0x00007eff8c11ce60 id: 1, name: "new name", replaces_employee_id: 5>,
#<Employee:0x00007eff8c11cd20 id: 2, name: "copy of ", replaces_employee_id: nil>,
#<Employee:0x00007eff8c11cbe0 id: 3, name: "copy of new name", replaces_employee_id: 2>,
#<Employee:0x00007eff8c11caa0 id: 4, name: "copy of new name", replaces_employee_id: 3>,
#<Employee:0x00007eff8c11c960 id: 5, name: "copy of new name", replaces_employee_id: 4>]
评论
current = Employee.create!; current.replaces_employee = current.dup; current.save!; Employee.all.as_json #=> [{"id"=>1, "replaces_employee_id"=>2}, {"id"=>2, "replaces_employee_id"=>nil}]
employees
replaces_employee
add_column :employees, :replaces_employee_id, :integer
integer
temp_clone = create_deep_clone; self.replaces_employee = temp_clone; temp_clone.update_attributes!(bla bla bla); self.save
deep_cloneable
#create_deep_clone
update_attributes!
replaces_employee
self.save
UPDATE "employees" SET "<additional updates>", "replaces_employee_id"
replaces_employee_id