diff --git a/CHANGELOG.md b/CHANGELOG.md index 24760e14d..9502d9ab3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Allow monetizing methods with kwargs - Fix money_only_cents for negative money +- Allow `super` when overriding methods ## 1.15.0 diff --git a/Gemfile b/Gemfile index ebddec725..e77017e3f 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ platforms :jruby do end platforms :ruby do - gem "sqlite3" + gem "sqlite3", '~> 1.4' end platform :mri do diff --git a/lib/money-rails/active_record/monetizable.rb b/lib/money-rails/active_record/monetizable.rb index 4b6b5febf..0f904947e 100644 --- a/lib/money-rails/active_record/monetizable.rb +++ b/lib/money-rails/active_record/monetizable.rb @@ -9,6 +9,8 @@ class ReadOnlyCurrencyException < MoneyRails::Error; end extend ActiveSupport::Concern module ClassMethods + MODULE_NAME = :DynamicMoneyAttributes + def monetized_attributes monetized_attributes = @monetized_attributes || {}.with_indifferent_access @@ -116,23 +118,31 @@ def monetize(*fields) end end - - # Getter for monetized attribute - define_method name do |*args, **kwargs| - read_monetized name, subunit_name, options, *args, **kwargs + if const_defined?(MODULE_NAME, false) + mod = const_get(MODULE_NAME) + else + mod = const_set(MODULE_NAME, Module.new) + include mod end - # Setter for monetized attribute - define_method "#{name}=" do |value| - write_monetized name, subunit_name, value, validation_enabled, instance_currency_name, options - end + mod.module_eval do + # Getter for monetized attribute + define_method name do |*args, **kwargs| + read_monetized name, subunit_name, options, *args, **kwargs + end + + # Setter for monetized attribute + define_method "#{name}=" do |value| + write_monetized name, subunit_name, value, validation_enabled, instance_currency_name, options + end - if validation_enabled - # Ensure that the before_type_cast value is cleared when setting - # the subunit value directly - define_method "#{subunit_name}=" do |value| - instance_variable_set "@#{name}_money_before_type_cast", nil - write_attribute(subunit_name, value) + if validation_enabled + # Ensure that the before_type_cast value is cleared when setting + # the subunit value directly + define_method "#{subunit_name}=" do |value| + instance_variable_set "@#{name}_money_before_type_cast", nil + write_attribute(subunit_name, value) + end end end diff --git a/spec/active_record/monetizable_spec.rb b/spec/active_record/monetizable_spec.rb index 85dd378fb..a4a41112e 100644 --- a/spec/active_record/monetizable_spec.rb +++ b/spec/active_record/monetizable_spec.rb @@ -30,6 +30,23 @@ def update_product(*attributes) context ".monetized_attributes" do + it "allows adds methods to the inheritance chain" do + class MyProduct < ActiveRecord::Base + self.table_name = :products + monetize :price_cents + attr_reader :side_effect + + def price=(value) + @side_effect = true + super + end + end + + p = MyProduct.new(price: 10) + expect(p.price).to eq Money.new(10_00) + expect(p.side_effect).to be_truthy + end + class InheritedMonetizeProduct < Product monetize :special_price_cents end