Module: EasyRailsMoney::ActiveRecord::MoneyDsl::ClassMethods

Defined in:
lib/easy_rails_money/active_record/money_dsl.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#single_currencyObject

Returns the value of attribute single_currency.



10
11
12
# File 'lib/easy_rails_money/active_record/money_dsl.rb', line 10

def single_currency
  @single_currency
end

Instance Method Details

#money(column_name) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/easy_rails_money/active_record/money_dsl.rb', line 48

def money column_name
  money_column = "#{column_name}_money"
  currency_column = "#{column_name}_currency"
  single_currency_column = "currency"
  
  if single_currency?
    define_method column_name do |*args|
      money = send(money_column)
      currency = send(single_currency_column)
      
      if money
        Money.new(money, currency)
      else
        nil
      end
    end

    define_method "#{column_name}=" do |value|
      raise ::ArgumentError.new("only Integer or nil accepted") unless (value.kind_of?(Integer) || value.is_a?(NilClass))
      
      send("#{money_column}=", value)
      # currency is stored in a seperate common column
      return Money.new(value, self.currency)
    end # define_method setter
  else
    # TODO: test if Memoization will make any difference
    define_method column_name do |*args|
      money = send(money_column)
      currency = send(currency_column) || EasyRailsMoney.default_currency
      
      if money
        Money.new(money, currency)
      else
        nil
      end
    end
    
    define_method "#{column_name}=" do |value|
      raise ::ArgumentError.new("only Money or nil accepted") unless (value.kind_of?(Money) || value.is_a?(NilClass))
      
      if value
        send("#{money_column}=", value.fractional)
        # it is stored in the database as a string but the Money
        # object exposes it as a Symbol. so we store it as a
        # String for consistency
        send("#{currency_column}=", value.currency.id.to_s)
        return value
      else
        send("#{money_column}=", nil)
        send("#{currency_column}=", nil)
        return nil
      end
    end # define_method setter
  end
end

#new(attributes = nil, options = {}) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/easy_rails_money/active_record/money_dsl.rb', line 35

def new(attributes = nil, options = {})
  instance = super
  # single currency is defined
  if single_currency?
    if attributes && attributes[:currency]
      instance.currency = EasyRailsMoney::MoneyDslHelper.to_currency(attributes[:currency]).id.to_s
    else
      instance.currency = instance.class.single_currency
    end
  end
  instance
end

#single_currency?Boolean

Returns:

  • (Boolean)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/easy_rails_money/active_record/money_dsl.rb', line 12

def single_currency?
  # if we define a ActiveRecord object with a money column
  # "before" the table is defined. Then it will throw an error
  # and we will assume that a single currency is defined
  # So always restart the app after the migrations are run
  self.columns_hash.has_key? "currency"
rescue Object => err
  # leaky abstaction. database adapter is leaking through
  # postgres with activerecord throws an error of type PG::Error and sqlite of ActiveRecord::StatementInvalid
  # so we depend on the message, not the class. still need to test on other
  # database adapters because the message is not exactly the same
  if err.message =~ /Could not find table/ || err.message =~ /relation (.+) does not exist/
    return true
  else
    raise
  end
end

#with_currency(currency, &block) ⇒ Object



30
31
32
33
# File 'lib/easy_rails_money/active_record/money_dsl.rb', line 30

def with_currency currency, &block
  self.single_currency = EasyRailsMoney::MoneyDslHelper.to_currency(currency).id.to_s
  instance_eval &block
end