diff --git a/app/models/application_record.rb b/app/models/application_record.rb index b63caeb..94d5e15 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,3 +1,17 @@ class ApplicationRecord < ActiveRecord::Base + class << self + # Cached attribute has non-user assignable value calculated from other + # attributes' values on create/update. This simplifies and speeds up + # actions, especially for recursively calculated values. Because value can + # be changed on update, it is not same as #attr_readonly. + def attr_cached(*names) + names.each { |name| alias_method :"#{name}=", :assign_cached_attribute } + end + end + + def assign_cached_attribute(value) + raise ActiveRecord::ReadonlyAttributeError + end + primary_abstract_class end diff --git a/app/models/quantity.rb b/app/models/quantity.rb index ed5fe4e..8330bff 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -1,5 +1,6 @@ class Quantity < ApplicationRecord ATTRIBUTES = [:name, :description, :parent_id] + attr_cached :depth, :pathname belongs_to :user, optional: true belongs_to :parent, optional: true, class_name: "Quantity" @@ -70,10 +71,6 @@ class Quantity < ApplicationRecord self[:depth] = parent&.depth&.succ || 0 end - def depth=(value) - raise ActiveRecord::ReadonlyAttributeError - end - scope :defaults, ->{ where(user: nil) } # Return: ordered [sub]hierarchy