我正在编写一个重新分配多态集合的方法,例如:
class Color < ApplicationRecord
belongs_to :colorable, polymorphic: true
end
class Table < ApplicationRecord
has_many :colors, as: :colorable
end
当我重新分配集合时,集合的现有元素的所有者连接字段已无效:
table.colors = new_colors_array
执行此查询:
UPDATE "colors" SET "colorable_id" = $1, "colorable_type" = $2 WHERE "colors"."colorable_id" = $3 AND "colors"."colorable_type" = $4 AND ("colors"."id" = $5 OR "colors"."id" = $6) [["colorable_id", nil], ["colorable_type", nil], ["colorable_id", "THE_TABLE_ID"], ["colorable_type", "Table"], ["id", "THE_COLOR_ID_1"], ["id", "THE_COLOR_ID_2"]]
它会导致此错误:
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "colorable_type" of relation "colors" violates not-null constraint
我可以先做:
table.colors.destroy_all
但是包含所有这些逻辑的方法应该不会在数据库中进行任何持久更改。允许开发人员在准备好时制作
table.save
。
进行集合替换但在调用
colorable.save
之前仍不对数据库进行任何持久更改的策略是什么?
我尝试过:
table.colors.clear # => touches DB
table.colors = [] # => touches DB
table.colors.reset # => touches DB
table.color.replace(new_colors_array) # => touches DB
ActiveRecord 实际上有一个方法来管理这些情况:
我们可以这样使用它:
def assign_colors(new_colors)
colors.each do |color|
color.mark_for_destruction
end
new_colors.each do |new_color|
colors << new_color
end
end