money-rails 1.13.3 → 1.13.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94253df4c6ac9ec75bfc1b569d6d05a96082846df1c7e2ab61d65cc56cf10183
4
- data.tar.gz: 8fbcf7e06595b836c03d12d77bba6db42fbf40abc5b1de44e7c6311ffca4f01f
3
+ metadata.gz: 618663a78af12610ff9901dd5ed3b3e5e5bf74d6d24b65141a52b2811179a0d8
4
+ data.tar.gz: 0724c64933122f73af34f1ad606c309e40c224a8b8636053ca437145527a8490
5
5
  SHA512:
6
- metadata.gz: a3f73a3833288cc529da04343d58ce82dabaa3563c61281712a8e5d975f3c60cacce5ff37b9b5422bacbf6f6c0606468643145376521925b9db26281748150fb
7
- data.tar.gz: 035af0f28d1aae1e28a970938f402a32c5de2eb1abd62bc2d36808f366dfe60f92f06aa4c5dddf9f940f85b20776deb9707def03b65544aedb6c9883dd8c67ac
6
+ metadata.gz: d0b87a85f4fe133e3fc75d75722c42dbb445c05cc98ebe7d242d8b63a27d8b879d324d37a8ca9b1ee24fddc8c0381152cd04e449dc8f8c041ec1598371760551
7
+ data.tar.gz: c984f12a0162f918b6d5c67b009da28d37a96a63ee0db664a8778e03503d60064ad9e8227d2e1d4fd37f61098f235445f0b959b7612aa503a1b90416f70b69c0
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.13.4
4
+
5
+ - Fix validator race condition
6
+ - Add Danish translation for errors
7
+ - Change Money fields to Decimal in Rails Admin
8
+ - Run hooks after active_record.initialize_database
9
+ - Add optional currency argument to "#currency_symbol" helper
10
+ - Rails 6.1 support
11
+
3
12
  ## 1.13.3
4
13
 
5
14
  - Add Money#to_hash for JSON serialization
data/README.md CHANGED
@@ -116,7 +116,7 @@ end
116
116
 
117
117
  Notice. Default value of currency field, generated by migration's helper, is USD. To override these defaults, you need change default_currency in money initializer and run migrations.
118
118
 
119
- The ```add_money``` helper is reversible, so you an use it inside ```change```
119
+ The ```add_money``` helper is reversible, so you can use it inside ```change```
120
120
  migrations. If you're writing separate ```up``` and ```down``` methods, you
121
121
  can use the ```remove_money``` helper.
122
122
 
@@ -306,7 +306,7 @@ object using EUR as their currency, instead of the default USD.
306
306
 
307
307
  By passing the option ```:with_currency``` to the ```monetize``` macro call,
308
308
  with a currency code (symbol or string) or a callable object (object that responds to the method ```call```) that returns a currency code, as its value, you can define a currency in a more granular
309
- way. This will you attach the given currency only to the specified monetized model
309
+ way. This will let you attach the given currency only to the specified monetized model
310
310
  attribute (allowing you to, for example, monetize different attributes of the same model with different currencies.).
311
311
 
312
312
  This allows you to override both the model level and the global
@@ -0,0 +1,4 @@
1
+ da:
2
+ errors:
3
+ messages:
4
+ invalid_currency: skal være en gyldig valuta (f.eks. '100', '5%{decimal}24', eller '123%{thousands}456%{decimal}78'). Fik %{currency}
@@ -1,44 +1,60 @@
1
1
  module MoneyRails
2
2
  module ActiveModel
3
3
  class MoneyValidator < ::ActiveModel::Validations::NumericalityValidator
4
- def validate_each(record, attr, _value)
5
- reset_memoized_variables!
6
- @record = record
7
- @attr = attr
4
+ class Details < Struct.new(:raw_value, :thousands_separator, :decimal_mark)
5
+ def abs_raw_value
6
+ @abs_raw_value ||= raw_value.to_s.sub(/^\s*-/, "").strip
7
+ end
8
8
 
9
- subunit_attr = @record.class.monetized_attributes[@attr.to_s]
9
+ def decimal_pieces
10
+ @decimal_pieces ||= abs_raw_value.split(decimal_mark)
11
+ end
12
+ end
13
+
14
+ def validate_each(record, attr, _value)
15
+ subunit_attr = record.class.monetized_attributes[attr.to_s]
16
+ currency = record.public_send("currency_for_#{attr}")
10
17
 
11
18
  # WARNING: Currently this is only defined in ActiveRecord extension!
12
- before_type_cast = :"#{@attr}_money_before_type_cast"
13
- @raw_value = @record.try(before_type_cast)
19
+ before_type_cast = :"#{attr}_money_before_type_cast"
20
+ raw_value = record.try(before_type_cast)
14
21
 
15
22
  # If raw value is nil and changed subunit is nil, then
16
23
  # nil is a assigned value, else we should treat the
17
24
  # subunit value as the one assigned.
18
- if @raw_value.nil? && @record.public_send(subunit_attr)
19
- subunit_value = @record.public_send(subunit_attr)
20
- @raw_value = subunit_value.to_f / currency.subunit_to_unit
25
+ if raw_value.nil? && record.public_send(subunit_attr)
26
+ subunit_value = record.public_send(subunit_attr)
27
+ raw_value = subunit_value.to_f / currency.subunit_to_unit
21
28
  end
22
29
 
23
- return if options[:allow_nil] && @raw_value.nil?
30
+ return if options[:allow_nil] && raw_value.nil?
24
31
 
25
- # Set this before we modify @raw_value below.
26
- stringy = @raw_value.present? && !@raw_value.is_a?(Numeric) && !@raw_value.is_a?(Money)
32
+ # Set this before we modify raw_value below.
33
+ stringy = raw_value.present? && !raw_value.is_a?(Numeric) && !raw_value.is_a?(Money)
27
34
 
28
35
  if stringy
36
+ # TODO: This is supporting legacy behaviour where a symbol can come from a i18n locale,
37
+ # however practical implications of that are most likely non-existent
38
+ symbol = lookup(:symbol, currency) || currency.symbol
39
+
29
40
  # remove currency symbol
30
- @raw_value = @raw_value.to_s.gsub(symbol, "")
41
+ raw_value = raw_value.to_s.gsub(symbol, "")
31
42
  end
32
43
 
33
- normalize_raw_value!
34
- super(@record, @attr, @raw_value)
44
+ # Cache abs_raw_value before normalizing because it's used in
45
+ # many places and relies on the original raw_value.
46
+ details = generate_details(raw_value, currency)
47
+ normalized_raw_value = normalize(details)
35
48
 
36
- if stringy && record_does_not_have_error?
37
- add_error if
38
- value_has_too_many_decimal_points ||
39
- thousand_separator_after_decimal_mark ||
40
- invalid_thousands_separation
41
- end
49
+ super(record, attr, normalized_raw_value)
50
+
51
+ return unless stringy
52
+ return if record_already_has_error?(record, attr, normalized_raw_value)
53
+
54
+ add_error!(record, attr, details) if
55
+ value_has_too_many_decimal_points(details) ||
56
+ thousand_separator_after_decimal_mark(details) ||
57
+ invalid_thousands_separation(details)
42
58
  end
43
59
 
44
60
  private
@@ -48,70 +64,45 @@ module MoneyRails
48
64
  thousands_separator: ','
49
65
  }.freeze
50
66
 
51
- def record_does_not_have_error?
52
- !@record.errors.added?(@attr, :not_a_number, value: @raw_value)
53
- end
67
+ def generate_details(raw_value, currency)
68
+ thousands_separator = lookup(:thousands_separator, currency)
69
+ decimal_mark = lookup(:decimal_mark, currency)
54
70
 
55
- def reset_memoized_variables!
56
- [:currency, :decimal_mark, :thousands_separator, :symbol,
57
- :abs_raw_value, :decimal_pieces, :pieces_array].each do |var_name|
58
- ivar_name = :"@_#{var_name}"
59
- remove_instance_variable(ivar_name) if instance_variable_defined?(ivar_name)
60
- end
71
+ Details.new(raw_value, thousands_separator, decimal_mark)
61
72
  end
62
73
 
63
- def currency
64
- @_currency ||= @record.public_send("currency_for_#{@attr}")
74
+ def record_already_has_error?(record, attr, raw_value)
75
+ record.errors.added?(attr, :not_a_number, value: raw_value)
65
76
  end
66
77
 
67
- def decimal_mark
68
- @_decimal_mark ||= lookup(:decimal_mark)
69
- end
78
+ def add_error!(record, attr, details)
79
+ attr_name = attr.to_s.tr('.', '_').humanize
80
+ attr_name = record.class.human_attribute_name(attr, default: attr_name)
70
81
 
71
- def thousands_separator
72
- @_thousands_separator ||= lookup(:thousands_separator)
82
+ record.errors.add(attr, :invalid_currency, {
83
+ thousands: details.thousands_separator,
84
+ decimal: details.decimal_mark,
85
+ currency: details.abs_raw_value,
86
+ attribute: attr_name
87
+ })
73
88
  end
74
89
 
75
- # TODO: This is supporting legacy behaviour where a symbol can come from a i18n locale,
76
- # however practical implications of that are most likely non-existent
77
- def symbol
78
- @_symbol ||= lookup(:symbol) || currency.symbol
90
+ def value_has_too_many_decimal_points(details)
91
+ ![1, 2].include?(details.decimal_pieces.length)
79
92
  end
80
93
 
81
- def abs_raw_value
82
- @_abs_raw_value ||= @raw_value.to_s.sub(/^\s*-/, "").strip
94
+ def thousand_separator_after_decimal_mark(details)
95
+ details.thousands_separator.present? &&
96
+ details.decimal_pieces.length == 2 &&
97
+ details.decimal_pieces[1].include?(details.thousands_separator)
83
98
  end
84
99
 
85
- def add_error
86
- attr_name = @attr.to_s.tr('.', '_').humanize
87
- attr_name = @record.class.human_attribute_name(@attr, default: attr_name)
100
+ def invalid_thousands_separation(details)
101
+ pieces_array = details.decimal_pieces[0].split(details.thousands_separator.presence)
88
102
 
89
- @record.errors.add(@attr, :invalid_currency,
90
- { thousands: thousands_separator,
91
- decimal: decimal_mark,
92
- currency: abs_raw_value,
93
- attribute: attr_name })
94
- end
95
-
96
- def decimal_pieces
97
- @_decimal_pieces ||= abs_raw_value.split(decimal_mark)
98
- end
99
-
100
- def value_has_too_many_decimal_points
101
- ![1, 2].include?(decimal_pieces.length)
102
- end
103
-
104
- def pieces_array
105
- @_pieces_array ||= decimal_pieces[0].split(thousands_separator.presence)
106
- end
107
-
108
- def thousand_separator_after_decimal_mark
109
- thousands_separator.present? && decimal_pieces.length == 2 && decimal_pieces[1].include?(thousands_separator)
110
- end
111
-
112
- def invalid_thousands_separation
113
103
  return false if pieces_array.length <= 1
114
104
  return true if pieces_array[0].length > 3
105
+
115
106
  pieces_array[1..-1].any? do |thousands_group|
116
107
  thousands_group.length != 3
117
108
  end
@@ -119,18 +110,15 @@ module MoneyRails
119
110
 
120
111
  # Remove thousands separators, normalize decimal mark,
121
112
  # remove whitespaces and _ (E.g. 99 999 999 or 12_300_200.20)
122
- def normalize_raw_value!
123
- # Cache abs_raw_value before normalizing because it's used in
124
- # many places and relies on the original @raw_value.
125
- abs_raw_value
126
-
127
- @raw_value = @raw_value.to_s
128
- .gsub(thousands_separator, '')
129
- .gsub(decimal_mark, '.')
113
+ def normalize(details)
114
+ details.raw_value
115
+ .to_s
116
+ .gsub(details.thousands_separator, '')
117
+ .gsub(details.decimal_mark, '.')
130
118
  .gsub(/[\s_]/, '')
131
119
  end
132
120
 
133
- def lookup(key)
121
+ def lookup(key, currency)
134
122
  if locale_backend
135
123
  locale_backend.lookup(key, currency) || DEFAULTS[key]
136
124
  else
@@ -209,7 +209,7 @@ module MoneyRails
209
209
 
210
210
  if MoneyRails::Configuration.preserve_user_input
211
211
  value_before_type_cast = instance_variable_get "@#{name}_money_before_type_cast"
212
- if errors[name.to_sym].present?
212
+ if errors.has_key?(name.to_sym)
213
213
  result.define_singleton_method(:to_s) { value_before_type_cast }
214
214
  result.define_singleton_method(:format) { |_| value_before_type_cast }
215
215
  end
@@ -1,8 +1,7 @@
1
1
  module MoneyRails
2
2
  module ActionViewExtension
3
-
4
- def currency_symbol
5
- content_tag(:span, Money.default_currency.symbol, class: "currency_symbol")
3
+ def currency_symbol(currency = Money.default_currency)
4
+ content_tag(:span, Money::Currency.find(currency).symbol, class: "currency_symbol")
6
5
  end
7
6
 
8
7
  def humanized_money(value, options={})
@@ -18,7 +18,13 @@ module MoneyRails
18
18
  else
19
19
  false
20
20
  end
21
- current_adapter = ::ActiveRecord::Base.connection_config[:adapter]
21
+
22
+ current_adapter = if ::ActiveRecord::Base.respond_to?(:connection_db_config)
23
+ ::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter]
24
+ else
25
+ ::ActiveRecord::Base.connection_config[:adapter]
26
+ end
27
+
22
28
  postgresql_with_money = rails42 && PG_ADAPTERS.include?(current_adapter)
23
29
  end
24
30
  end
@@ -8,7 +8,7 @@ module RailsAdmin
8
8
  module Config
9
9
  module Fields
10
10
  module Types
11
- class Money < RailsAdmin::Config::Fields::Types::Integer
11
+ class Money < RailsAdmin::Config::Fields::Types::Decimal
12
12
  RailsAdmin::Config::Fields::Types::register(self)
13
13
 
14
14
  register_instance_option :pretty_value do
@@ -1,6 +1,6 @@
1
1
  module MoneyRails
2
2
  class Railtie < ::Rails::Railtie
3
- initializer 'moneyrails.initialize' do
3
+ initializer 'moneyrails.initialize', after: 'active_record.initialize_database' do
4
4
  MoneyRails::Hooks.init
5
5
  end
6
6
  end
@@ -1,3 +1,3 @@
1
1
  module MoneyRails
2
- VERSION = '1.13.3'
2
+ VERSION = '1.13.4'
3
3
  end
@@ -20,6 +20,14 @@ if defined? ActiveRecord
20
20
  Service.create(charge_cents: 2000, discount_cents: 120)
21
21
  end
22
22
 
23
+ def update_product(*attributes)
24
+ if defined?(::ActiveRecord::VERSION) && ::ActiveRecord::VERSION::MAJOR >= 5
25
+ product.update(*attributes)
26
+ else
27
+ product.update_attributes(*attributes)
28
+ end
29
+ end
30
+
23
31
  context ".monetized_attributes" do
24
32
 
25
33
  class InheritedMonetizeProduct < Product
@@ -73,7 +81,7 @@ if defined? ActiveRecord
73
81
  end
74
82
 
75
83
  it "correctly updates from a Money object using update_attributes" do
76
- expect(product.update_attributes(price: Money.new(215, "USD"))).to be_truthy
84
+ expect(update_product(price: Money.new(215, "USD"))).to be_truthy
77
85
  expect(product.price_cents).to eq(215)
78
86
  end
79
87
 
@@ -187,8 +195,8 @@ if defined? ActiveRecord
187
195
  end
188
196
 
189
197
  it "respects numericality validation when using update_attributes" do
190
- expect(product.update_attributes(price_cents: "some text")).to be_falsey
191
- expect(product.update_attributes(price_cents: 2000)).to be_truthy
198
+ expect(update_product(price_cents: "some text")).to be_falsey
199
+ expect(update_product(price_cents: 2000)).to be_truthy
192
200
  end
193
201
 
194
202
  it "uses numericality validation on money attribute" do
@@ -415,8 +423,8 @@ if defined? ActiveRecord
415
423
  end
416
424
 
417
425
  it "respects numericality validation when using update_attributes on money attribute" do
418
- expect(product.update_attributes(price: "some text")).to be_falsey
419
- expect(product.update_attributes(price: Money.new(320, 'USD'))).to be_truthy
426
+ expect(update_product(price: "some text")).to be_falsey
427
+ expect(update_product(price: Money.new(320, 'USD'))).to be_truthy
420
428
  end
421
429
 
422
430
  it "uses i18n currency format when validating" do
@@ -5,6 +5,18 @@ describe 'MoneyRails::ActionViewExtension', type: :helper do
5
5
  subject { helper.currency_symbol }
6
6
  it { is_expected.to be_a String }
7
7
  it { is_expected.to include Money.default_currency.symbol }
8
+
9
+ context 'with given currency' do
10
+ subject { helper.currency_symbol(Money::Currency.find(:brl)) }
11
+ it { is_expected.to include Money::Currency.find(:brl).symbol }
12
+ it { is_expected.to include Money::Currency.find(:brl).symbol }
13
+ end
14
+
15
+ context 'with given currency symbol' do
16
+ subject { helper.currency_symbol(:brl) }
17
+ it { is_expected.to include Money::Currency.find(:brl).symbol }
18
+ it { is_expected.to include Money::Currency.find(:brl).symbol }
19
+ end
8
20
  end
9
21
 
10
22
  describe '#humanized_money' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.3
4
+ version: 1.13.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Loupasakis
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-10-16 00:00:00.000000000 Z
13
+ date: 2021-01-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: money
@@ -135,6 +135,7 @@ files:
135
135
  - LICENSE
136
136
  - README.md
137
137
  - Rakefile
138
+ - config/locales/money.da.yml
138
139
  - config/locales/money.en.yml
139
140
  - lib/generators/money_rails/initializer_generator.rb
140
141
  - lib/generators/templates/money.rb
@@ -250,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
251
  - !ruby/object:Gem::Version
251
252
  version: '0'
252
253
  requirements: []
253
- rubygems_version: 3.0.3
254
+ rubygems_version: 3.1.2
254
255
  signing_key:
255
256
  specification_version: 4
256
257
  summary: Money gem integration with Rails