如何修改依赖::destroy 查询 has_many 关系
Posted
技术标签:
【中文标题】如何修改依赖::destroy 查询 has_many 关系【英文标题】:How can I modify the dependent: :destroy query for has_many relationship 【发布时间】:2016-07-29 18:46:31 【问题描述】:我有一个名为Family
的模型,它与Parent
有has_many
关系:
class Family < ActiveRecord::Base
has_many :parents, :dependent => :destroy
end
当用户删除Family
时,它应该删除所有关联的Parent
。
有一个主要问题:我有一个多租户环境(使用 Apartment gem),并且父母处于公共架构中。因此,我只需要选择在同一帐户中应该删除的父母。
现在,当在 Family
上调用 destroy 时,我得到:
SELECT "public"."users".* FROM "public"."users" WHERE "public"."users"."type" IN ('Parent') AND "public"."users"."family_id" = $FAMILY_ID
我需要它:
SELECT "public"."users".* FROM "public"."users" WHERE "public"."users"."type" IN ('Parent') AND "public"."users"."family_id" = $FAMILY_ID AND "public"."users"."account_id" = $CURRENT_ACCOUNT_ID
有没有办法覆盖Family.destroy
方法,使其只选择正确的关联记录?
【问题讨论】:
您可以在此处添加范围以过滤has_many :parents, ->() <some-condition>, :dependent => :destroy
。这样,您可以有条件地删除记录。将 CURRENT_ACCOUNT_ID
作为参数传递给范围 lambda。
@ArupRakshit 如果CURRENT_ACCOUNT_ID
仅在控制器中可用,因为它是请求的一部分,这可能吗?
我没听懂你。 :) 但是你可以从任何地方传递像Family.parents(CURRENT_ACCOUNT_ID).destroy_all
这样的值。
@ArupRakshit 好的,但我如何让has_many :parents, :dependent => :destroy
做到这一点?我应该删除dependent: :destroy
并在Family.destroy
上执行回调吗?或者覆盖Family.destroy
?
你不需要重写方法,你会像我上面那样调用它。通过这个:dependent => :destroy
,你告诉AR,删除你从调用family.parents(CURRENT_ACCOUNT_ID).destroy_all
获得的孩子,其中family
是Family
的一个实例。
【参考方案1】:
这是我采用的解决方案。我从family.rb
模型中的has_many :parents
关系中删除了dependent: :destroy
子句。相反,我在 Family 控制器的 destroy
操作中执行级联删除:
def destroy
@family = Family.find(params[:id])
authorize @family
parents = @family.parents.for_account(current_account.id)
@family.destroy
if @family.destroyed?
parents.destroy_all
end
redirect_to families_path
end
我必须在控制器中执行此操作,因为控制器知道 current_account
而模型不知道。 Parent 模型上的for_account
方法如下所示:
scope :for_account, -> (id) where(:account_id => id)
【讨论】:
以上是关于如何修改依赖::destroy 查询 has_many 关系的主要内容,如果未能解决你的问题,请参考以下文章
ActiveRecord:为啥 has_many 依赖: :destroy 不起作用?
markdown has_manyに依赖:destroyをつけたときの挙动
Vue.extend构造器和$mount实例构造组件后可以用$destroy()进行卸载,$forceUpdate()进行更新,$nextTick()数据修改