不可变的活动记录关系和属性(设置者)

时间:2009-07-28 21:02:31

标签: ruby-on-rails ruby activerecord rspec

我打算在某些情况下解决我们遇到的问题;我们可能需要使属性或关系不可变,即一旦写入属性就永远写入。 attr_readonly不合适,因为这对关系不起作用,所以我试图在这里证明这个概念:

http://pastie.org/562329

这显示了我的测试,一个示例实现(理想情况下我会移动到一个模块) - 我不确定这是否是一种重载关系设置器的可接受方式,我已经将测试扩展到现在读取{{ 3}}这可能是矫枉过正,但帮助我理解customer_id如何与客户作为一种属性与关系的关系,但我很乐意被纠正!

2 个答案:

答案 0 :(得分:4)

我没有尝试过,但我认为update_attribute(:customer_id => 1)会在某些情况下中断。另外,我真的不喜欢覆盖属性设置器的想法。

更好的(恕我直言)方法是覆盖'before_update'并且如果有任何改变则取一个not。您可以使用Dirty模块执行此操作。看看这个:

我没有对此进行测试,但它会采用以下方式:

class Order < ActiveRecord::Base
  IMMUTABLE = %w{customer_id notes}

  before_save do |record|
    return false if IMMUTABLE.any? { |attr| record.changed.has_key?(attr) }
  end
end

当然,您可以更好地了解如何处理IMMUTABLE。如果将其放在模块中,则before_save必须位于Module#included挂钩

答案 1 :(得分:-2)

您可以通过以下方式定义setter方法:在第一次写入之后,该方法将自身重新定义为无操作。

class Order < ActiveRecord::Base
  def customer= c
    if c
      super
      class << self
        def customer= c
        end
      end
    end
  end
end