简体   繁体   中英

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. 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.
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.

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. 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 . 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.

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. 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

You can also make a record become readonly by using readonly!.

Documentation can be found here: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-readonly-21

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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