module MoneyRails::ActiveRecord::Monetizable
Public Instance Methods
currency_for(name, instance_currency_name, field_currency_name)
click to toggle source
# File lib/money-rails/active_record/monetizable.rb, line 277 def currency_for(name, instance_currency_name, field_currency_name) if instance_currency_name.present? && respond_to?(instance_currency_name) && Money::Currency.find(public_send(instance_currency_name)) Money::Currency.find(public_send(instance_currency_name)) elsif field_currency_name.respond_to?(:call) Money::Currency.find(field_currency_name.call(self)) elsif field_currency_name Money::Currency.find(field_currency_name) elsif self.class.respond_to?(:currency) self.class.currency else Money.default_currency end end
read_monetized(name, subunit_name, options = {}, *args)
click to toggle source
# File lib/money-rails/active_record/monetizable.rb, line 181 def read_monetized(name, subunit_name, options = {}, *args) # Get the cents amount = public_send(subunit_name, *args) return if amount.nil? && options[:allow_nil] # Get the currency object attr_currency = public_send("currency_for_#{name}") # Get the cached value memoized = instance_variable_get("@#{name}") # Dont create a new Money instance if the values haven't been changed. if memoized && memoized.cents == amount if memoized.currency == attr_currency result = memoized else memoized_amount = memoized.amount.to_money(attr_currency) write_attribute subunit_name, memoized_amount.cents # Cache the value (it may be nil) result = instance_variable_set("@#{name}", memoized_amount) end elsif amount.present? # If amount is NOT nil (or empty string) load the amount in a Money amount = Money.new(amount, attr_currency) # Cache the value (it may be nil) result = instance_variable_set("@#{name}", amount) end if MoneyRails::Configuration.preserve_user_input value_before_type_cast = instance_variable_get "@#{name}_money_before_type_cast" if errors.has_key?(name.to_sym) result.define_singleton_method(:to_s) { value_before_type_cast } result.define_singleton_method(:format) { |_| value_before_type_cast } end end result end
write_monetized(name, subunit_name, value, validation_enabled, instance_currency_name, options)
click to toggle source
# File lib/money-rails/active_record/monetizable.rb, line 221 def write_monetized(name, subunit_name, value, validation_enabled, instance_currency_name, options) # Keep before_type_cast value as a reference to original input instance_variable_set "@#{name}_money_before_type_cast", value # Use nil or get a Money object if options[:allow_nil] && value.blank? money = nil else if value.is_a?(Money) money = value else begin money = value.to_money(public_send("currency_for_#{name}")) rescue NoMethodError return nil rescue Money::Currency::UnknownCurrency, Monetize::ParseError => e raise MoneyRails::Error, e.message if MoneyRails.raise_error_on_money_parsing return nil end end end # Update cents if !validation_enabled # We haven't defined our own subunit writer, so we can invoke # the regular writer, which works with store_accessors public_send("#{subunit_name}=", money.try(:cents)) elsif self.class.respond_to?(:attribute_aliases) && self.class.attribute_aliases.key?(subunit_name) # If the attribute is aliased, make sure we write to the original # attribute name or an error will be raised. # (Note: 'attribute_aliases' doesn't exist in Rails 3.x, so we # can't tell if the attribute was aliased.) original_name = self.class.attribute_aliases[subunit_name.to_s] write_attribute(original_name, money.try(:cents)) else write_attribute(subunit_name, money.try(:cents)) end if money_currency = money.try(:currency) # Update currency iso value if there is an instance currency attribute if instance_currency_name.present? && respond_to?("#{instance_currency_name}=") public_send("#{instance_currency_name}=", money_currency.iso_code) else current_currency = public_send("currency_for_#{name}") if current_currency != money_currency.id raise ReadOnlyCurrencyException.new("Can't change readonly currency '#{current_currency}' to '#{money_currency}' for field '#{name}'") if MoneyRails.raise_error_on_money_parsing return nil end end end # Save and return the new Money object instance_variable_set "@#{name}", money end