【问题标题】:Soft-delete on has_many through association通过关联软删除 has_many
【发布时间】:2012-05-13 13:45:36
【问题描述】:

在has_many上通过关联实现软删除的最简单方法是什么?

我想要的是这样的:

class Company > ActiveRecord::Base
  has_many :staffings
  has_many :users, through: :staffings, conditions: {staffings: {active: true}}
end

我想通过以下方式使用Company#users

  • Company#users 应该是一个正常的关联,以便它适用于表单并且不会违反现有合同。
  • 向公司添加用户时,创建了一个带有active: true 的新Staffing
  • 从公司删除用户时,现有的Staffing 会更新active: false(目前它刚刚被删除)。
  • 向公司添加以前删除的用户时(以便Staffing#active == falseStaffing 更新为active: true

我考虑过覆盖Company#users= 方法,但它确实不够好,因为还有其他更新关联的方法。

所以问题是:如何在Company#users 关联上实现解释的行为?

谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord orm associations


    【解决方案1】:

    has_many :through 关联实际上只是语法糖。当您需要进行繁重的工作时,我建议您拆分逻辑并提供适当的方法和范围。了解如何覆盖 callbacks 对于这类事情也很有用。

    这将使您开始对User 进行软删除并在User 之后创建Staffings

    class Company < ActiveRecord::Base
      has_many :staffings
      has_many :users, through: :staffings, conditions: ['staffings.active = ?', true]
    end
    
    class Staffing < ActiveRecord::Base
      belongs_to :company
      has_one :user
    end
    
    class User < ActiveRecord::Base
      belongs_to :staffing
    
      # after callback fires, create a staffing
      after_create {|user| user.create_staffing(active: true)}
    
      # override the destroy method since you 
      # don't actually want to destroy the User
      def destroy
        run_callbacks :delete do
          self.staffing.active = false if self.staffing
        end
      end
    end
    

    【讨论】:

    • 我很清楚回调和所有这些。我认为你没有读过这个问题。我怎样才能按照我描述的方式使用Company#users
    • 我的回答没有为您的四个用例中的哪一个提供解决方案?您可以保留 Company 的定义,并添加 after_create 回调和覆盖的 destroy 方法以及您提到的所有功能。也许对您打算如何使用Company#users 进行一些澄清会有所帮助,因为您实际上并没有解释您打算如何使用Company#users,只是需要满足四份合同。
    • 我已经稍微更新了这个问题。请花点时间阅读。
    猜你喜欢
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多