使用has_and_belongs_to_many_association
class Category
has_and_belongs_to_many :projects
end
我想在保存类别
之前使用before_filter设置项目before_filter :set_projects, :only => [:create, :update]
def set_projects
@category.assign_attributes({projects: Project.all})
end
这种方法很有效,除非无法保存类别并且存在回滚。这些项目仍在数据库中更新。
为什么这一行
@category.assign_attributes({projects: Project.all})
立即生成这些数据库记录?
BEGIN
INSERT INTO "categories_projects" ("category_id", "project_id") VALUES (86, 1)
INSERT INTO "categories_projects" ("category_id", "project_id") VALUES (86, 2)
INSERT INTO "categories_projects" ("category_id", "project_id") VALUES (86, 3)
COMMIT
我想在提交这些新的categories_projects关系之前等待@ category.save。 如何推迟这些提交?
请注意,我无法修改主“更新”操作。我必须在过滤器和回调之前/之后使用,以覆盖我的应用程序的当前功能。
------编辑----------
好的,仔细阅读文档后here,我想我有一个解决方案:
何时保存对象?
将对象分配给has_and_belongs_to_many关联时, 该对象会自动保存(以便更新连接 表)。如果在一个语句中分配多个对象,那么它们就是 全部保存。
如果要将对象分配给has_and_belongs_to_many 没有保存对象的关联,请使用collection.build 方法
我将尝试使用collection.build方法。您是否知道如何使用现有项目?
答案 0 :(得分:0)
为什么不在Category
回拨中将其移入after_save
模型? e.g。
class Category
#based on comment need virtual attribute
attr_accessor :assignable_projects
after_save :set_projects
private
def set_projects
self.assign_attributes({projects: self.assignable_projects})
end
end
由于您只需要为特定项目设置此项,因此您需要创建一个虚拟属性。此属性将存储在实例中,但不会保存到数据库中。要做到这一点,我们添加一个attr_accessor
行,它将创建所需的getter和setter方法。
然后在控制器中
class CategoriesController < ApplicationContoller
before_filter :set_assignable_projects, only: [:create,:update]
private
def set_assignable_projects
@category.assignable_projects = params[:project_ids]
end
end
在运行category
验证并成功保存类别后,将触发此事件。然后,它将使用before_filter
中指定的值来创建关联。由于assign_attributes
不会再次调用save
,因此会避免无限循环。您也可以将其置于after_validation
回调中,但请确保在使用self.errors.empty?
之前检查assign_attributes
,否则您将与现在的船在同一条船上。
如果category
无法保存,则仍会为该实例设置assignable_projects
,因此它们会在渲染视图中显示失败的保存。