class MoneyRails::ActiveModel::MoneyValidator
Constants
- DEFAULTS
Private Instance Methods
add_error!(record, attr, details)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 78 def add_error!(record, attr, details) attr_name = attr.to_s.tr('.', '_').humanize attr_name = record.class.human_attribute_name(attr, default: attr_name) record.errors.add(attr, :invalid_currency, thousands: details.thousands_separator, decimal: details.decimal_mark, currency: details.abs_raw_value, attribute: attr_name ) end
generate_details(raw_value, currency)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 67 def generate_details(raw_value, currency) thousands_separator = lookup(:thousands_separator, currency) decimal_mark = lookup(:decimal_mark, currency) Details.new(raw_value, thousands_separator, decimal_mark) end
invalid_thousands_separation(details)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 100 def invalid_thousands_separation(details) pieces_array = details.decimal_pieces[0].split(details.thousands_separator.presence) return false if pieces_array.length <= 1 return true if pieces_array[0].length > 3 pieces_array[1..-1].any? do |thousands_group| thousands_group.length != 3 end end
locale_backend()
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 129 def locale_backend Money.locale_backend end
lookup(key, currency)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 121 def lookup(key, currency) if locale_backend locale_backend.lookup(key, currency) || DEFAULTS[key] else DEFAULTS[key] end end
normalize(details)
click to toggle source
Remove thousands separators, normalize decimal mark, remove whitespaces and _ (E.g. 99 999 999 or 12_300_200.20)
# File lib/money-rails/active_model/validator.rb, line 113 def normalize(details) details.raw_value .to_s .gsub(details.thousands_separator, '') .gsub(details.decimal_mark, '.') .gsub(/[\s_]/, '') end
record_already_has_error?(record, attr, raw_value)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 74 def record_already_has_error?(record, attr, raw_value) record.errors.added?(attr, :not_a_number, value: raw_value) end
thousand_separator_after_decimal_mark(details)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 94 def thousand_separator_after_decimal_mark(details) details.thousands_separator.present? && details.decimal_pieces.length == 2 && details.decimal_pieces[1].include?(details.thousands_separator) end
validate_each(record, attr, _value)
click to toggle source
Calls superclass method
# File lib/money-rails/active_model/validator.rb, line 14 def validate_each(record, attr, _value) subunit_attr = record.class.monetized_attributes[attr.to_s] currency = record.public_send("currency_for_#{attr}") # WARNING: Currently this is only defined in ActiveRecord extension! before_type_cast = :"#{attr}_money_before_type_cast" raw_value = record.try(before_type_cast) # If raw value is nil and changed subunit is nil, then # nil is a assigned value, else we should treat the # subunit value as the one assigned. if raw_value.nil? && record.public_send(subunit_attr) subunit_value = record.public_send(subunit_attr) raw_value = subunit_value.to_f / currency.subunit_to_unit end return if options[:allow_nil] && raw_value.nil? # Set this before we modify raw_value below. stringy = raw_value.present? && !raw_value.is_a?(Numeric) && !raw_value.is_a?(Money) if stringy # TODO: This is supporting legacy behaviour where a symbol can come from a i18n locale, # however practical implications of that are most likely non-existent symbol = lookup(:symbol, currency) || currency.symbol # remove currency symbol raw_value = raw_value.to_s.gsub(symbol, "") end # Cache abs_raw_value before normalizing because it's used in # many places and relies on the original raw_value. details = generate_details(raw_value, currency) normalized_raw_value = normalize(details) super(record, attr, normalized_raw_value) return unless stringy return if record_already_has_error?(record, attr, normalized_raw_value) add_error!(record, attr, details) if value_has_too_many_decimal_points(details) || thousand_separator_after_decimal_mark(details) || invalid_thousands_separation(details) end
value_has_too_many_decimal_points(details)
click to toggle source
# File lib/money-rails/active_model/validator.rb, line 90 def value_has_too_many_decimal_points(details) ![1, 2].include?(details.decimal_pieces.length) end