Module: MoneyAttribute::Macro::CompositeClassMethods

Defined in:
lib/money_attribute/macro.rb

Overview

:nodoc:

Instance Method Summary collapse

Instance Method Details

#amount_extractor_for(column_name) ⇒ Object



41
# File 'lib/money_attribute/macro.rb', line 41

def amount_extractor_for(column_name) = integer_column?(column_name) ? :subunits : :to_d

#assert_columns_exist!(name, composite) ⇒ Object

Raises:

  • (ArgumentError)


31
32
33
34
35
36
37
38
39
# File 'lib/money_attribute/macro.rb', line 31

def assert_columns_exist!(name, composite)
  missing = composite.values - attribute_names
  return if missing.empty?

  raise ArgumentError,
        "Could not find columns for :#{name} money attribute. " \
        "Expected: #{composite.values.join(', ')}, " \
        "Found: #{attribute_names.join(', ')}"
end

#build_money_constructor(method, default) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/money_attribute/macro.rb', line 52

def build_money_constructor(method, default)
  lambda do |amount, currency|
    next nil if amount.nil?

    resolved = Mint::Currency.resolve(currency.presence || default) || 'XXX'
    Mint::Money.public_send(method, amount, resolved)
  end
end

#define_composite_money_attribute(name, mapping, currency) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/money_attribute/macro.rb', line 66

def define_composite_money_attribute(name, mapping, currency)
  aggregated = resolve_composite_for(name, mapping:)

  composed_of(name.to_sym, {
                allow_nil: true,
                class_name: 'Mint::Money',
                constructor: money_constructor_for(aggregated[:amount]),
                converter: Converter.new(currency),
                mapping: {
                  aggregated[:amount] => amount_extractor_for(aggregated[:amount]),
                  aggregated[:currency] => :currency_code
                }
              })
end

#integer_column?(column_name) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
64
# File 'lib/money_attribute/macro.rb', line 61

def integer_column?(column_name)
  col = columns.find { |c| c.name == column_name }
  %i[integer bigint].include?(col&.type)
end

#money_constructor_for(amount_column) ⇒ Object



43
44
45
46
47
48
49
50
# File 'lib/money_attribute/macro.rb', line 43

def money_constructor_for(amount_column)
  default = MoneyAttribute.default_currency
  if integer_column?(amount_column)
    build_money_constructor(:from_subunits, default)
  else
    build_money_constructor(:from, default)
  end
end

#resolve_composite_for(name, mapping:) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/money_attribute/macro.rb', line 21

def resolve_composite_for(name, mapping:)
  composite = { amount: "#{name}_amount", currency: "#{name}_currency" }

  composite[:amount]   = mapping[:amount].to_s if mapping&.key?(:amount)
  composite[:currency] = mapping[:currency].to_s if mapping&.key?(:currency)

  assert_columns_exist!(name, composite)
  composite
end

#resolve_composite_mapping(name) ⇒ Object



10
11
12
13
14
15
16
17
18
19
# File 'lib/money_attribute/macro.rb', line 10

def resolve_composite_mapping(name)
  columns = attribute_names
  if columns.include?("#{name}_currency")
    return { amount: name, currency: :"#{name}_currency" } if columns.include?(name)

    nil
  elsif name == 'amount' && columns.include?('currency')
    { amount: name, currency: :currency }
  end
end