简体   繁体   English

如何防止对模型进行修改?

[英]How do I prevent modifications to a Model?

In a current project, I have a model called Box that stores items from an online store. 在当前项目中,我有一个名为Box的模型,该模型存储在线商店中的商品。 A box belongs to a Package (which defines price, payment conditions, etc) and has many Item and ExtraItem objects that hold products and extra offers included to the box. 包装盒属于“ Package (定义价格,付款条件等),并具有许多ItemExtraItem对象,用于容纳包装盒中包含的产品和额外优惠。
When the customer fills a box with products and extra offers and proceeds to checkout, a new object of class Purchase is created, with a reference to the Box that contains its items. 当客户用产品和额外优惠填充盒子并进行结帐时,将创建一个类Purchase的新对象,并引用包含其项目的Box

A Purchase has an attribute named total which gets the total monetary value from the box that contains the items (on a before_validation hook) and keeps record of the total paid even if products prices change. Purchase具有名为total的属性,该属性从包含项目的框(在before_validation挂钩上)获取总货币值,并且即使产品价格发生变化也保留已支付总金额的记录。 My concern is that even after a purchase is confirmed and created, the box that belongs to it can still be changed (items can be added/removed), creating records that don't reflect the reality at the time of the purchase. 我担心的是,即使在确认并创建购买后,仍可以更改其所属的 (可以添加/删除项目),创建的记录不能反映购买时的实际情况。

To prevent changes to box, i've created a method that hooks on after_initialize and initialize methods to prevent specific attribute-changing methods from being called if a locked attribute is set to true . 为了防止对box进行更改,我创建了一个方法,该方法挂在after_initialize和initialize方法上,以防止在锁定属性设置为true的情况下调用特定的属性更改方法。 It works as following: 它的工作方式如下:

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

It basically freezes the associations (a box has many items , extraitems and garrisons ) and redefines certain methods to raise a LockedBoxError exception when called. 它基本上冻结了关联(一个盒子包含许多物品额外 物品驻军 ),并重新定义了某些方法,以在调用时引发LockedBoxError异常。

As this seems to be working as intended, i'm really worried that this approach can cause unexpected behavior and i'm looking for a way to achieve the same effect without the need to override methods the way i'm doing! 由于这似乎按预期工作,我真的很担心这种方法会导致意外的行为,我正在寻找一种方法来实现相同的效果, 无需覆盖我正在做的方法!

Do you folks know any way i can possibly do this? 你们知道我有什么办法吗? I really appreciate your help! 非常感谢您的帮助! :) :)

I would use attr_readonly to mark your attributes read only. 我将使用attr_readonly将您的属性标记为只读。 They will be created when you make the record, but will not be updatable after that. 它们将在您创建记录时创建,但此后将无法更新。

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

You can also make a record become readonly by using readonly!. 您也可以使用readonly!使记录变为只读。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM