如何在没有身份映射的ActiveRecord对象上设置持久化实例变量?

时间:2011-08-04 12:15:58

标签: ruby-on-rails activerecord

在我意识到发生了什么事之前,我一直在努力解决问题。

我想建立一个必须至少有一名成员的委员会。为此,每个成员在被销毁之前检查它不是最后一个成员。

下面的代码应该可以防止最后一个成员被摧毁,除非委员会本身被摧毁,在这种情况下它会自我毁灭。

class Committee < ActiveRecord::Base

  has_many :committee_members
  before_destroy: { @destroy_initiated = true }

  def destroy_initiated?
    @destroy_initiated
  end

end

class CommitteeMember < ActiveRecord::Base

  belongs_to :committee
  before_destroy :ensure_not_last

  def ensure_not_last
    unless self.committee.destroy_initiated?
      if self.committee.committee_members.count == 1
        raise 'You cannot remove the last committe member. Try destroying the committee instead'
      end
    end
  end

end

问题

问题是每个委员会成员都引用了委员会对象的不同实例,它们都有不同的对象标识:

e.g。 #<Committee:0x00000105c41f20> v。#<Committee:0x00000105c2c3a0>

这意味着即使我在ID为20的委员会实例上设置@destroy_initiated为true,也不会在其委员会成员引用的实例上将其设置为true。

除了Rails 3.1,我知道它有一个身份图,是否有一个干净的解决方法,有一个实例变量,可用于委员会的所有实例?

我正在考虑做一个包含destroy_initiated地图的类变量?每个委员会ID,但这感觉非常混乱。

1 个答案:

答案 0 :(得分:0)

我不确定我是否可以在没有更多背景的情况下正确回答这个问题,但我可以给你一个可能的解决方案来思考......

在我刚刚投入生产的应用程序中,我们实际上将对象缓存为ApplicationController上的实例变量。然后,只要我们需要它,我们只需要实例变量而不是使用Active Record查找它。

class ApplicationController < ActionController::Base
  before_filter :set_committee

  def set_committee
    @committee ||= Committee.new()
  end
end

现在,在请求期间,从ApplicationController继承的任何内容都可以访问@committee对象。如果您可以使用类似的模式(不必是应用程序控制器,可以只是任何其他控制器),那么在请求期间您基本上会有一个“全局”变量。