money-rails 1.0.0 → 1.1.0

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
  SHA1:
3
- metadata.gz: 1045d1d93a0e6e7f720ee329933a3f1821210f39
4
- data.tar.gz: 9059b8e4f70988725a8009ec68fb7ac2548b0335
3
+ metadata.gz: 7f7362d98f56cc0f9a7e99d5aae5385d555786dd
4
+ data.tar.gz: fab18c41c2b15e4916400013a7b60e6b00ae39e7
5
5
  SHA512:
6
- metadata.gz: c7b9b0c7492769ffcfac56971877b9c0a58821613c4a9401f0440ecb8358276b729a303678a9f1e3ba644d674fdec6e18cd3ee6dce6a6601998b9a6e2bd7059d
7
- data.tar.gz: 02b1bd7f8bd5ee35cc6365f77bc2d1b571f117a261c7e2aa7416ad012964fd956acfc588751076ee83b7eae8072289afbeac254fe3aa52c640c0a058fd5cadb1
6
+ metadata.gz: c79ba8f99be3130f51e9b6d2f3092a6c5d4d2247f4325573e07e8e3b00c839a65b471f5937df5085b1cac396c7dbbb9e5f08d1b8aa027f80700fb141f87beb5f
7
+ data.tar.gz: 452e693682d7f1d45849c14ac44f78ba157cdcd85f9ede1f68a2f419084f666159ac4dd0c439abcf1429303e6256b6e044a04bacf72a15bad1fd0f438649d1fa
data/README.md CHANGED
@@ -259,7 +259,7 @@ object using EUR as their currency, instead of the default USD.
259
259
  By passing the option ```:with_currency``` to the ```monetize``` macro call,
260
260
  with a currency code as its value, you can define a currency in a more granular
261
261
  way. This will you attach the given currency only to the specified monetized model
262
- attribute (allowing you tom for example, monetize different attributes of the same model with different currencyies.).
262
+ attribute (allowing you to, for example, monetize different attributes of the same model with different currencies.).
263
263
 
264
264
  This allows you to override both the model level and the global
265
265
  default currencies:
@@ -321,16 +321,24 @@ MoneyRails.configure do |config|
321
321
 
322
322
  # To set the default currency
323
323
  #
324
- config.default_currency = :usd
324
+ # config.default_currency = :usd
325
+
326
+ # Set default bank object
327
+ #
328
+ # Example:
329
+ # config.default_bank = EuCentralBank.new
325
330
 
326
- # Add custom exchange rates
327
- config.add_rate "USD", "CAD", 1.24515
328
- config.add_rate "CAD", "USD", 0.803115
331
+ # Add exchange rates to current money bank object.
332
+ # (The conversion rate refers to one direction only)
333
+ #
334
+ # Example:
335
+ # config.add_rate "USD", "CAD", 1.24515
336
+ # config.add_rate "CAD", "USD", 0.803115
329
337
 
330
338
  # To handle the inclusion of validations for monetized fields
331
339
  # The default value is true
332
340
  #
333
- config.include_validations = true
341
+ # config.include_validations = true
334
342
 
335
343
  # Default ActiveRecord migration configuration values for columns:
336
344
  #
@@ -354,6 +362,7 @@ MoneyRails.configure do |config|
354
362
 
355
363
  # Register a custom currency
356
364
  #
365
+ # Example:
357
366
  # config.register_currency = {
358
367
  # :priority => 1,
359
368
  # :iso_code => "EU4",
@@ -379,15 +388,17 @@ MoneyRails.configure do |config|
379
388
  #
380
389
  # set to BigDecimal::ROUND_HALF_EVEN by default
381
390
  #
382
- config.rounding_mode = BigDecimal::ROUND_HALF_UP
391
+ # config.rounding_mode = BigDecimal::ROUND_HALF_UP
383
392
 
384
- # Set money formatted output globally.
393
+ # Set default money format globally.
385
394
  # Default value is nil meaning "ignore this option".
386
- # Options are nil, true, false.
395
+ # Example:
387
396
  #
388
- # config.no_cents_if_whole = nil
389
- # config.symbol = nil
390
- # config.sign_before_symbol = nil
397
+ # config.default_format = {
398
+ # :no_cents_if_whole => nil,
399
+ # :symbol => nil,
400
+ # :sign_before_symbol => nil
401
+ # }
391
402
  end
392
403
  ```
393
404
 
@@ -403,56 +414,26 @@ end
403
414
  only! This rate is added to the attached bank object.
404
415
  * ```default_bank```: The default bank object holding exchange rates etc.
405
416
  (https://github.com/RubyMoney/money#currency-exchange)
406
- * ```no_cents_if_whole```: Force `Money#format` method to use its value as the default for ```no_cents_if_whole``` key.
407
- * ```symbol```: Use its value as the default for ```symbol``` key in
408
- `Money#format` method.
409
- * ```sign_before_symbol```: Force `Money#format` to place the negative sign before the currency symbol.
417
+ * ```default_format```: Force `Money#format` to use these options for formatting.
410
418
  * ```amount_column```: Provide values for the amount column (holding the fractional part of a money object).
411
419
  * ```currency_column```: Provide default values or even disable (`present: false`) the currency column.
412
420
  * ```rounding_mode```: Set Money.rounding_mode to one of the BigDecimal constants
413
421
 
414
422
  ### Helpers
415
423
 
416
- * the `currency_symbol` helper method
424
+ _For examples below, `@money_object == <Money fractional:650 currency:USD>`_
417
425
 
418
- ```
419
- <%= currency_symbol %>
420
- ```
421
- This will render a `span` dom element with the default currency symbol.
422
-
423
- * the `humanized_money` helper method
424
-
425
- ```
426
- <%= humanized_money @money_object %>
427
- ```
428
- This will render a formatted money value without the currency symbol and
429
- without the cents part if it contains only zeros (uses
430
- `:no_cents_if_whole flag`).
426
+ | Helper | Result |
427
+ |:--- |:--- |
428
+ | `currency_symbol` | `<span class="currency_symbol">$</span>` |
429
+ | `humanized_money @money_object` | 6.50 |
430
+ | `humanized_money_with_symbol @money_object` | $6.50 |
431
+ | `money_without_cents @money_object` | 6 |
432
+ | `money_without_cents_and_with_symbol @money_object` | $6 |
431
433
 
432
- * humanize with symbol helper
434
+ #### `no_cents_if_whole`
433
435
 
434
- ```
435
- <%= humanized_money_with_symbol @money_object %>
436
- ```
437
- This will render a formatted money value including the currency symbol and
438
- without the cents part if it contains only zeros.
439
-
440
- * get the money value without the cents part
441
-
442
- ```
443
- <%= money_without_cents @money_object %>
444
- ```
445
- This will render a formatted money value without the currency symbol and
446
- without the cents part.
447
-
448
- * get the money value without the cents part and including the currency
449
- symbol
450
-
451
- ```
452
- <%= money_without_cents_and_with_symbol @money_object %>
453
- ```
454
- This will render a formatted money value including the currency symbol and
455
- without the cents part.
436
+ `humanized_money` and `humanized_money_with_symbol` will not render the cents part if it contains only zeros, unless `config.no_cents_if_whole` is set to `false` in the `money.rb` configuration (default: true).
456
437
 
457
438
  ### Testing
458
439
 
@@ -58,10 +58,13 @@ MoneyRails.configure do |config|
58
58
  # :decimal_mark => ","
59
59
  # }
60
60
 
61
- # Set money formatted output globally.
61
+ # Set default money format globally.
62
62
  # Default value is nil meaning "ignore this option".
63
- # Options are nil, true, false.
63
+ # Example:
64
64
  #
65
- # config.no_cents_if_whole = nil
66
- # config.symbol = nil
65
+ # config.default_format = {
66
+ # :no_cents_if_whole => nil,
67
+ # :symbol => nil,
68
+ # :sign_before_symbol => nil
69
+ # }
67
70
  end
@@ -90,7 +90,7 @@ module MoneyRails
90
90
  end
91
91
 
92
92
  def pieces_array
93
- @_pieces_array ||= decimal_pieces[0].split(thousands_separator)
93
+ @_pieces_array ||= decimal_pieces[0].split(thousands_separator.presence)
94
94
  end
95
95
 
96
96
  def invalid_thousands_separation
@@ -17,7 +17,7 @@ module MoneyRails
17
17
  if options[:field_currency] || options[:target_name] ||
18
18
  options[:model_currency]
19
19
  ActiveSupport::Deprecation.warn("You are using the old " \
20
- "argument keys of monetize command! Instead use :as, " \
20
+ "argument keys of the monetize command! Instead use :as, " \
21
21
  ":with_currency or :with_model_currency")
22
22
  end
23
23
 
@@ -38,7 +38,7 @@ module MoneyRails
38
38
 
39
39
  # Form target name for the money backed ActiveModel field:
40
40
  # if a target name is provided then use it
41
- # if there is a "_{column.postfix}" suffix then just remove it to create the target name
41
+ # if there is a "{column.postfix}" suffix then just remove it to create the target name
42
42
  # if none of the previous is the case then use a default suffix
43
43
  if name
44
44
  name = name.to_s
@@ -50,8 +50,11 @@ module MoneyRails
50
50
  end
51
51
 
52
52
  # Create a reverse mapping of the monetized attributes
53
- @monetized_attributes ||= {}
54
- @monetized_attributes[name.to_sym] = subunit_name
53
+ @monetized_attributes ||= {}.with_indifferent_access
54
+ if @monetized_attributes[name].present?
55
+ raise ArgumentError, "#{self} already has a monetized attribute called '#{name}'"
56
+ end
57
+ @monetized_attributes[name] = subunit_name
55
58
  class << self
56
59
  def monetized_attributes
57
60
  @monetized_attributes || superclass.monetized_attributes
@@ -151,12 +154,25 @@ module MoneyRails
151
154
  rescue ArgumentError
152
155
  raise if MoneyRails.raise_error_on_money_parsing
153
156
  return nil
157
+ rescue Money::Currency::UnknownCurrency
158
+ raise if MoneyRails.raise_error_on_money_parsing
159
+ return nil
154
160
  end
155
161
  end
156
162
  end
157
163
 
158
164
  # Update cents
159
- write_attribute(subunit_name, money.try(:cents))
165
+ # If the attribute is aliased, make sure we write to the original
166
+ # attribute name or an error will be raised.
167
+ # (Note: 'attribute_aliases' doesn't exist in Rails 3.x, so we
168
+ # can't tell if the attribute was aliased.)
169
+ if self.class.respond_to?(:attribute_aliases) &&
170
+ self.class.attribute_aliases.key?(subunit_name)
171
+ original_name = self.class.attribute_aliases[subunit_name.to_s]
172
+ write_attribute(original_name, money.try(:cents))
173
+ else
174
+ write_attribute(subunit_name, money.try(:cents))
175
+ end
160
176
 
161
177
  money_currency = money.try(:currency)
162
178
 
@@ -167,7 +183,7 @@ module MoneyRails
167
183
  send("#{instance_currency_name}=", money_currency.try(:iso_code))
168
184
  else
169
185
  current_currency = send("currency_for_#{name}")
170
- if money_currency && current_currency != money_currency
186
+ if money_currency && current_currency != money_currency.id
171
187
  raise "Can't change readonly currency '#{current_currency}' to '#{money_currency}' for field '#{name}'"
172
188
  end
173
189
  end
@@ -177,7 +193,7 @@ module MoneyRails
177
193
  end
178
194
 
179
195
  if validation_enabled
180
- # Ensure that the before_type_cast value is updated when settin
196
+ # Ensure that the before_type_cast value is updated when setting
181
197
  # the subunit value directly
182
198
  define_method "#{subunit_name}=" do |value|
183
199
  before_type_cast = value.to_f / send("currency_for_#{name}").subunit_to_unit
@@ -21,12 +21,12 @@ module MoneyRails
21
21
  # Configuration parameters
22
22
 
23
23
  def default_currency
24
- Money.default_currency
24
+ Money::Currency.new(Money.default_currency)
25
25
  end
26
26
 
27
27
  # Set default currency of money library
28
28
  def default_currency=(currency_name)
29
- Money.default_currency = Money::Currency.new(currency_name)
29
+ Money.default_currency = currency_name
30
30
  set_amount_column_for_default_currency!
31
31
  set_currency_column_for_default_currency!
32
32
  end
@@ -90,6 +90,9 @@ module MoneyRails
90
90
  mattr_accessor :sign_before_symbol
91
91
  @@sign_before_symbol = nil
92
92
 
93
+ mattr_accessor :default_format
94
+ @@default_format = nil
95
+
93
96
  # Configure whether to raise exception when an improper value
94
97
  # is going to be converted to a Money object.
95
98
  mattr_accessor :raise_error_on_money_parsing
@@ -7,7 +7,6 @@ class Money
7
7
  rules = normalize_formatting_rules(rules)
8
8
 
9
9
  # Apply global defaults for money only for non-nil values
10
- # TODO: Add here more setting options
11
10
  defaults = {
12
11
  no_cents_if_whole: MoneyRails::Configuration.no_cents_if_whole,
13
12
  symbol: MoneyRails::Configuration.symbol,
@@ -16,6 +15,10 @@ class Money
16
15
 
17
16
  rules.reverse_merge!(defaults)
18
17
 
18
+ unless MoneyRails::Configuration.default_format.nil?
19
+ rules.reverse_merge!(MoneyRails::Configuration.default_format)
20
+ end
21
+
19
22
  format_without_settings(rules)
20
23
  end
21
24
 
@@ -14,7 +14,7 @@ class Money
14
14
  # this custom class from it.
15
15
  def demongoize(object)
16
16
  if object.is_a?(Hash)
17
- object = object.symbolize_keys
17
+ object = object.deep_symbolize_keys
18
18
  object.has_key?(:cents) ? ::Money.new(object[:cents], object[:currency_iso]) : nil
19
19
  else
20
20
  nil
@@ -27,7 +27,7 @@ class Money
27
27
  case
28
28
  when object.is_a?(Money) then object.mongoize
29
29
  when object.is_a?(Hash) then
30
- object.symbolize_keys! if object.respond_to?(:symbolize_keys!)
30
+ object.deep_symbolize_keys! if object.respond_to?(:deep_symbolize_keys!)
31
31
  ::Money.new(object[:cents], object[:currency_iso]).mongoize
32
32
  when object.respond_to?(:to_money) then
33
33
  begin
@@ -27,29 +27,22 @@ module MoneyRails
27
27
  end
28
28
 
29
29
  def matches?(actual)
30
- @actual = actual
31
-
32
- money_attr = @as.presence || @attribute.to_s.sub(/_cents$/, "")
33
-
34
- matched = true
35
-
36
- if actual.respond_to?(money_attr)
37
- if @allow_nil
38
- matched &&= actual.send(money_attr).nil?
39
- actual.send("#{money_attr}=", 0)
40
- end
41
- matched &&= actual.send(money_attr).instance_of?(Money)
42
-
43
- if @currency_iso
44
- matched &&= actual.send(money_attr.to_sym).currency.id == @currency_iso
45
- end
30
+ if actual.is_a?(Class)
31
+ @actual = actual.new
46
32
  else
47
- matched = false
33
+ @actual = actual.class.new
48
34
  end
49
35
 
50
- matched
36
+ @money_attribute = @as.presence || @attribute.to_s.sub(/_cents$/, "")
37
+ @money_attribute_setter = "#{@money_attribute}="
38
+
39
+ object_responds_to_attributes? &&
40
+ test_allow_nil &&
41
+ is_monetized? &&
42
+ test_currency_iso
51
43
  end
52
44
 
45
+
53
46
  def description
54
47
  desc = "monetize #{@attribute}"
55
48
  desc << " as #{@as}" if @as
@@ -73,6 +66,35 @@ module MoneyRails
73
66
  end
74
67
  alias_method :failure_message_for_should_not, :failure_message_when_negated # RSpec 1.2, 2.x, and minitest-matchers
75
68
  alias_method :negative_failure_message, :failure_message_when_negated # RSpec 1.1
69
+
70
+ private
71
+
72
+ def object_responds_to_attributes?
73
+ @actual.respond_to?(@attribute) && @actual.respond_to?(@money_attribute)
74
+ end
75
+
76
+ def test_allow_nil
77
+ if @allow_nil
78
+ @actual.send(@money_attribute_setter, "")
79
+ @actual.send(@money_attribute).nil?
80
+ else
81
+ true
82
+ end
83
+ end
84
+
85
+ def is_monetized?
86
+ @actual.send(@money_attribute_setter, 1)
87
+ @actual.send(@money_attribute).instance_of?(Money)
88
+ end
89
+
90
+ def test_currency_iso
91
+ if @currency_iso
92
+ @actual.send(@money_attribute).currency.id == @currency_iso
93
+ else
94
+ true
95
+ end
96
+ end
97
+
76
98
  end
77
99
  end
78
100
  end
@@ -1,3 +1,3 @@
1
1
  module MoneyRails
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
data/money-rails.gemspec CHANGED
@@ -32,6 +32,6 @@ Gem::Specification.new do |s|
32
32
  s.add_dependency "railties", ">= 3.0"
33
33
 
34
34
  s.add_development_dependency "rails", ">= 3.0"
35
- s.add_development_dependency "rspec-rails", "~> 2.10"
35
+ s.add_development_dependency "rspec-rails", "~> 3.0"
36
36
  s.add_development_dependency 'database_cleaner', ['>= 0.8.0']
37
37
  end
@@ -53,8 +53,8 @@ if defined? ActiveRecord
53
53
  end
54
54
 
55
55
  context 'without currency column' do
56
- it { Item.columns_hash['price_without_currency_cents'].should_not be nil }
57
- it { Item.columns_hash['price_without_currency_currency'].should be nil }
56
+ it { expect(Item.columns_hash['price_without_currency_cents']).not_to be nil }
57
+ it { expect(Item.columns_hash['price_without_currency_currency']).to be nil }
58
58
  end
59
59
 
60
60
  context 'full options' do
@@ -69,7 +69,7 @@ if defined? ActiveRecord
69
69
  end
70
70
 
71
71
  describe 'currency' do
72
- it { Item.columns_hash['currency'].should_not be nil }
72
+ it { expect(Item.columns_hash['currency']).not_to be nil }
73
73
  end
74
74
  end
75
75
  end
@@ -87,13 +87,13 @@ if defined? ActiveRecord
87
87
  Item.reset_column_information
88
88
  end
89
89
 
90
- it { Item.columns_hash['price_cents'].should be nil }
91
- it { Item.columns_hash['price_currency'].should be nil }
90
+ it { expect(Item.columns_hash['price_cents']).to be nil }
91
+ it { expect(Item.columns_hash['price_currency']).to be nil }
92
92
 
93
- it { Item.columns_hash['price_without_currency_cents'].should be nil }
93
+ it { expect(Item.columns_hash['price_without_currency_cents']).to be nil }
94
94
 
95
- it { Item.columns_hash['prefix_price_with_full_options_postfix'].should be nil }
96
- it { Item.columns_hash['currency'].should be nil }
95
+ it { expect(Item.columns_hash['prefix_price_with_full_options_postfix']).to be nil }
96
+ it { expect(Item.columns_hash['currency']).to be nil }
97
97
  end
98
98
  end
99
99
  end
@@ -54,8 +54,8 @@ if defined? ActiveRecord
54
54
  end
55
55
 
56
56
  context 'without currency column' do
57
- it { Item.columns_hash['price_without_currency_cents'].should_not be nil }
58
- it { Item.columns_hash['price_without_currency_currency'].should be nil }
57
+ it { expect(Item.columns_hash['price_without_currency_cents']).not_to be nil }
58
+ it { expect(Item.columns_hash['price_without_currency_currency']).to be nil }
59
59
  end
60
60
 
61
61
  context 'full options' do
@@ -70,7 +70,7 @@ if defined? ActiveRecord
70
70
  end
71
71
 
72
72
  describe 'currency' do
73
- it { Item.columns_hash['currency'].should_not be nil }
73
+ it { expect(Item.columns_hash['currency']).not_to be nil }
74
74
  end
75
75
  end
76
76
  end
@@ -90,13 +90,13 @@ if defined? ActiveRecord
90
90
  Item.reset_column_information
91
91
  end
92
92
 
93
- it { Item.columns_hash['price_cents'].should be nil }
94
- it { Item.columns_hash['price_currency'].should be nil }
93
+ it { expect(Item.columns_hash['price_cents']).to be nil }
94
+ it { expect(Item.columns_hash['price_currency']).to be nil }
95
95
 
96
- it { Item.columns_hash['price_without_currency_cents'].should be nil }
96
+ it { expect(Item.columns_hash['price_without_currency_cents']).to be nil }
97
97
 
98
- it { Item.columns_hash['prefix_price_with_full_options_postfix'].should be nil }
99
- it { Item.columns_hash['currency'].should be nil }
98
+ it { expect(Item.columns_hash['prefix_price_with_full_options_postfix']).to be nil }
99
+ it { expect(Item.columns_hash['currency']).to be nil }
100
100
  end
101
101
  end
102
102
  end