cirandas.net

ref: master

app/models/concerns/currency_fields.rb


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
module CurrencyFields

  extend ActionView::Helpers::NumberHelper

  def self.parse_localized_number number
    return 0 if number.blank?
    number = number.to_s
    number.gsub! I18n.t("number.currency.format.unit"), ''
    begin
      # try simple conversation, in case it is a non localized number
      # this is the case of <input type=number />
      number = Float number
    rescue
      number.gsub! I18n.t("number.currency.format.delimiter"), ''
      number.gsub! I18n.t("number.currency.format.separator"), '.'
      number = number.to_f
    end
    number
  end

  def self.parse_currency currency
    self.parse_localized_number currency
  end

  def self.localized_number number
    # the maximum precision is 2, and we don't use number_with_precision
    # as we don't wan't a fixed precision (e.g. 1.00 is just 1.0)
    number_with_delimiter number.to_f.round 2
  end

  def self.number_as_currency_number number
    string = number_to_currency number, unit: ''
    string.gsub! ' ', '' if string
    string
  end

  def self.number_as_currency number
    number_to_currency number
  end

  module ClassMethods

    def has_number_with_locale attr
      # rake db:migrate run?
      return unless self.table_exists?

      # Rails doesn't define getters and setters for attributes
      define_method attr do
        self[attr]
      end if attr.to_s.in? self.column_names and not method_defined? attr
      define_method "#{attr}=" do |value|
        self[attr] = value
      end if attr.to_s.in? self.column_names and not method_defined? "#{attr}="

      if method_defined? "#{attr}="
        define_method "#{attr}_with_locale=" do |value|
          value = CurrencyFields.parse_localized_number value if value.is_a? String
          self.send "#{attr}_without_locale=", value
        end
        alias_method_chain "#{attr}=", :locale
      end

      define_method "#{attr}_localized" do |*args, &block|
        number = self.send attr, *args, &block
        CurrencyFields.localized_number number
      end
    end

    def has_currency attr
      self.has_number_with_locale attr

      define_method "#{attr}_as_currency" do |*args, &block|
        number = self.send attr, *args, &block
        CurrencyFields.number_as_currency number
      end
      define_method "#{attr}_as_currency_number" do |*args, &block|
        number = self.send attr, *args, &block
        CurrencyFields.number_as_currency_number number
      end
    end

  end

  module InstanceMethods

  end

end