我有三个型号User
Feature
UserFeature
class User < ActiveRecord::Base
has_many :user_features
has_many :features, through: :user_features
end
class Feature < ActiveRecord::Base
has_many :user_features
has_many :users, through: :user_features
end
class UserFeature < ActiveRecord::Base
belongs_to :user
belongs_to :feature
end
我已经在DB中创建了许多特性,并在使用以下代码创建用户时将特性与用户相关联
<%= form_for @user do |f| %>
// some user_fields
<% Feature.all.each do |feature| %>
<%= check_box "user[feature_ids][], feature.id %>
<% end %>
// submit button here
<% end %>
在我的UserController
中我有这样的代码
class UserController < ApplicationController
def create
@user = User.new(permit_params)
@user.save
end
def update
@user = User.find(params[:id])
@user.update_attributes(permit_params)
end
private
def permit_params
params.require(:user).permit(:name, :email, user_feature_ids: [])
end
end
当我提交时,它将创建和更新用户,并在UserFeature
表中为我选中的那些功能创建条目。
更新用户时,如果我未选中任何功能,则将从UserFeature
删除相关记录
这里没有任何问题,一切都按预期工作。
但是现在我想在删除user_feature时执行一些活动。
为此,我在UserFeature after_destroy :some_activity
中编写了一个回调
class UserFeature < ActiveRecord::Base
belongs_to :user
belongs_to :feature
after_destroy :some_activity
def some_activity
// some code
end
end
但是它不工作,当我检查为什么它在删除user_feature时不调用destroy调用时,我发现它将调用SQL查询,而不是在未选中的user_feature上调用destroy
。
这就是after
或before
destroy
回调不起作用的原因。
有谁能让我知道,如何才能在删除UserFeature
时执行任何活动?
2条答案
按热度按时间vs3odd8k1#
after_destroy
回调不会在delete
之后触发,因为delete
是这样实现的。引用docs:活动记录对象不会示例化,因此对象的回调不会执行,包括任何:依赖关联选项。[...]尽管它通常比替代方法#destroy快得多,但跳过回调可能会绕过应用程序中确保引用完整性或执行其他基本工作的业务逻辑。
您可以在关联定义上使用
after_remove
回调,而不是在关联类上使用after_destroy
回调,如Rails指南中关于关联回调所述。3b6akqbq2#
解决方案是不要将代码设置为使用"Automatic deletion of a join model"模式(因为此模式不会触发删除回调)。
相反,使用
accepts_nested_attributes_for
声明将代码设置为标准嵌套资源,该声明将触发删除回调。这些模型将是:
注:
has_many
声明中使用through:
,因为您不会使用它附带的getter/setter.feature_ids
。allow_destroy: true
选项的accepts_nested_attributes_for
声明。表格为:
注:
.fields_for
方法生成UserFeature
字段。:_destroy
。checked_value
必须为false
(如果选中,则不删除)unchecked_value
必须为true
(如果未选中,则执行删除)(基本)控制器将是: