0

在当前的项目中,我有一个名为的模型Box,用于存储来自在线商店的商品。一个盒子属于一个Package(它定义了价格、付款条件等),并且有许多Item对象ExtraItem,其中包含包含在盒子中的产品和额外优惠。
当客户用产品和额外优惠填充一个盒子并继续结帐时,Purchase会创建一个新的类对象,并引用Box包含其项目的 。

APurchase有一个名为total的属性,它从包含项目的盒子中获取总货币价值(在 before_validation 挂钩上),并且即使产品价格发生变化,也会记录支付的总金额。我担心的是,即使在确认并创建了购买后,属于它的盒子仍然可以更改(可以添加/删除项目),创建的记录不能反映购买时的实际情况。

为了防止对 box 进行更改,我创建了一个挂钩 after_initialize 和 initialize 方法的方法,以防止在锁定属性设置为true时调用特定的属性更改方法。它的工作原理如下:

def trigger_locked_box_behavior
  if locked?
    [:items,:extra_items,:garrisons].each { |p| (send("#{p.to_s}")).freeze }
    [:package=, :package_id=, :box_behavior_type=, :resource=, :resource_id=, :resource_type=].each do |param|
      class_eval do
        define_method(param) do |*args|
          raise LockedBoxError
        end
      end
    end
  end
end

它基本上冻结了关联(一个盒子有很多itemsextraitemsgarrisons)并重新定义某些方法以在调用时引发 LockedBoxError 异常。

由于这似乎按预期工作,我真的担心这种方法会导致意外行为,我正在寻找一种方法来实现相同的效果,而无需像我正在做的那样覆盖方法!

你们知道我有什么办法可以做到这一点吗?我真的很感谢你的帮助!:)

4

2 回答 2

2

我会使用 attr_readonly 将您的属性标记为只读。它们将在您制作记录时创建,但之后将无法更新。

http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-attr_readonly

于 2011-03-27T01:28:50.167 回答
2

您还可以使用 readonly! 使记录变为只读。

文档可以在这里找到:http: //api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-readonly-21

于 2011-03-27T09:01:41.983 回答