-1

我试图弄清楚如何在保存后回调中判断数组中发生了什么变化。这是我正在使用的代码示例:

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy
  has_many :subusers, :through => :user_maps, :dependent => :destroy

  has_many :inverse_user_maps, :class_name => "UserMap", :foreign_key => "subuser_id"
  has_one :parent, :through => :inverse_user_maps, :source => :user

  after_save :remove_subusers

  def remove_subusers
    if self.subuser_ids_were != self.subuser_ids
      leftover = self.subuser_ids_were - self.subuser_ids

      leftover.each do |subuser|
        subuser.destroy
      end
    end
  end
end

class UserMap < ActiveRecord::Base
  belongs_to :user
  belongs_to :subuser, :class_name => "User"
end

我正在使用 after_save 回调删除子用户,因为我无法通过 user_maps 获得依赖的销毁功能。有没有人对如何做到这一点有任何想法?

谢谢!

4

2 回答 2

0

您可以使用 Dirty 模块访问器http://ar.rubyonrails.org/classes/ActiveRecord/Dirty.html,如确定 Rails after_save 回调中更改了哪些属性?

在您的情况下,您拥有的处理程序after_save将有权访问subusers_change哪个是由两个元素组成的数组,第一个是前一个值,第二个是新值。

于 2011-10-02T11:22:01.873 回答
0

虽然严格来说不是您问题的答案,但我认为如果您尝试以下操作,您也许可以得到 :dependent => :destroy 工作......

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy
  has_many :subusers, :through => :user_maps # removing the :dependent => :destroy option
end

class UserMap < ActiveRecord::Base
  belongs_to :user
  belongs_to :subuser, :class_name => "User", :dependent => :destroy # add it here
end

通过将 :dependent => :destroy 选项移动到 UserMap 模型中的 belongs_to 关联,您可以通过 UserMap#destroy 方法设置级联删除。换句话说,调用 User#destroy 将为每个 UserMap 记录调用 UserMap#destroy,而后者又会为其 sub_user 记录调用 sub_user.destroy。

编辑

由于上面的解决方案不起作用,我的下一个建议是向 user_maps 关联添加回调,但是这带有一个警告,我将在之后添加

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy, :before_remove => :remove_associated_subuser

  def remove_associated_subuser(user_map)
    user_map.subuser.destroy
  end
end

警告

1) 使用 before_remove 回调意味着如果回调出错,则不会调用 user_map.destroy 函数

2)您将不得不使用 User 类上的方法销毁您的 UserMap 记录,例如...

# this will fire the callback
u = User.first
u.user_maps.destroy(u.user_maps.first)

# this WONT fire the callback
UserMap.first.destroy

综合考虑,这会让我感到紧张。我会首先尝试修改您的代码以使关联与同一个表的耦合少一点,因此 :dependent => :destroy 选项可以工作,如果您不能这样做,请在数据库上添加级联删除约束,至少你的关联总是会被删除,无论你在哪里/如何在你的 Rails 应用程序中销毁它。

于 2011-10-02T09:30:15.693 回答