如何修改依赖::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 的模型,它与Parenthas_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, -&gt;() &lt;some-condition&gt;, :dependent =&gt; :destroy。这样,您可以有条件地删除记录。将 CURRENT_ACCOUNT_ID 作为参数传递给范围 lambda。 @ArupRakshit 如果CURRENT_ACCOUNT_ID 仅在控制器中可用,因为它是请求的一部分,这可能吗? 我没听懂你。 :) 但是你可以从任何地方传递像Family.parents(CURRENT_ACCOUNT_ID).destroy_all 这样的值。 @ArupRakshit 好的,但我如何让has_many :parents, :dependent =&gt; :destroy 做到这一点?我应该删除dependent: :destroy 并在Family.destroy 上执行回调吗?或者覆盖Family.destroy 你不需要重写方法,你会像我上面那样调用它。通过这个:dependent =&gt; :destroy,你告诉AR,删除你从调用family.parents(CURRENT_ACCOUNT_ID).destroy_all获得的孩子,其中familyFamily的一个实例。 【参考方案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学习总结

Vue.extend构造器和$mount实例构造组件后可以用$destroy()进行卸载,$forceUpdate()进行更新,$nextTick()数据修改

如何使用依赖:销毁而不造成无限循环

如何使按钮自毁?