money-rails 1.12.0 → 1.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
 - data/CHANGELOG.md +31 -0
 - data/README.md +6 -5
 - data/Rakefile +17 -35
 - data/config/locales/money.da.yml +4 -0
 - data/lib/generators/templates/money.rb +23 -0
 - data/lib/money-rails/active_model/validator.rb +82 -78
 - data/lib/money-rails/active_record/migration_extensions/schema_statements_pg_rails4.rb +2 -2
 - data/lib/money-rails/active_record/monetizable.rb +1 -1
 - data/lib/money-rails/configuration.rb +1 -2
 - data/lib/money-rails/helpers/action_view_extension.rb +10 -3
 - data/lib/money-rails/hooks.rb +7 -1
 - data/lib/money-rails/money.rb +6 -1
 - data/lib/money-rails/mongoid/money.rb +28 -19
 - data/lib/money-rails/rails_admin.rb +1 -1
 - data/lib/money-rails/railtie.rb +1 -1
 - data/lib/money-rails/version.rb +1 -1
 - data/money-rails.gemspec +7 -1
 - data/spec/active_record/monetizable_spec.rb +40 -30
 - data/spec/configuration_spec.rb +3 -3
 - data/spec/dummy/app/assets/config/manifest.js +0 -0
 - data/spec/helpers/action_view_extension_spec.rb +33 -0
 - data/spec/money_spec.rb +40 -0
 - data/spec/mongoid/{four_spec.rb → mongoid_spec.rb} +10 -3
 - data/spec/mongoid/two_spec.rb +2 -2
 - metadata +16 -13
 - data/spec/mongoid/five_spec.rb +0 -117
 - data/spec/mongoid/three_spec.rb +0 -122
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 618663a78af12610ff9901dd5ed3b3e5e5bf74d6d24b65141a52b2811179a0d8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0724c64933122f73af34f1ad606c309e40c224a8b8636053ca437145527a8490
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d0b87a85f4fe133e3fc75d75722c42dbb445c05cc98ebe7d242d8b63a27d8b879d324d37a8ca9b1ee24fddc8c0381152cd04e449dc8f8c041ec1598371760551
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c984f12a0162f918b6d5c67b009da28d37a96a63ee0db664a8778e03503d60064ad9e8227d2e1d4fd37f61098f235445f0b959b7612aa503a1b90416f70b69c0
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,5 +1,36 @@ 
     | 
|
| 
       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 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## 1.13.3
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            - Add Money#to_hash for JSON serialization
         
     | 
| 
      
 15 
     | 
    
         
            +
            - Update initializer template with #locale_backend config
         
     | 
| 
      
 16 
     | 
    
         
            +
            - Rollback support for remove_monetize / remove_money DB helpers
         
     | 
| 
      
 17 
     | 
    
         
            +
            - Rails 6 support
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## 1.13.2
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            - Make validation compatible with Money.locale_backend
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ## 1.13.1
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            - Add a guard clause for "blank form" input (Mongoid)
         
     | 
| 
      
 26 
     | 
    
         
            +
            - Do not add extra errors in case attribute is not a number
         
     | 
| 
      
 27 
     | 
    
         
            +
            - Use Money.locale_backend instead of Money.use_i18n
         
     | 
| 
      
 28 
     | 
    
         
            +
            - Add money_only_cents helper method
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            ## 1.13.0
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            - Bump money version to ~> 6.13.0
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       3 
34 
     | 
    
         
             
            ## 1.12.0
         
     | 
| 
       4 
35 
     | 
    
         | 
| 
       5 
36 
     | 
    
         
             
            - Bump money version to ~> 6.12.0
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -22,7 +22,7 @@ welcome to contribute to the project. 
     | 
|
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
            Add this line to your application's Gemfile:
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                gem 'money-rails', '~>1'
         
     | 
| 
      
 25 
     | 
    
         
            +
                gem 'money-rails', '~>1.12'
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
            And then execute:
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
         @@ -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  
     | 
| 
      
 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
         
     | 
| 
         @@ -326,7 +326,7 @@ end 
     | 
|
| 
       326 
326 
     | 
    
         
             
            ```
         
     | 
| 
       327 
327 
     | 
    
         | 
| 
       328 
328 
     | 
    
         
             
            In this case ```product.bonus``` will return a Money object with GBP as its
         
     | 
| 
       329 
     | 
    
         
            -
            currency, whereas ```product.discount. 
     | 
| 
      
 329 
     | 
    
         
            +
            currency, whereas ```product.discount.currency.to_s # => EUR ```
         
     | 
| 
       330 
330 
     | 
    
         | 
| 
       331 
331 
     | 
    
         
             
            As mentioned earlier you can use an object that responds to the method ```call``` and accepts the model instance as a parameter. That means you can use a ```Proc``` or ```lambda``` (we would recommend ```lambda``` over ```Proc``` because of their [different control flow characteristics](https://stackoverflow.com/questions/1740046/whats-the-difference-between-a-proc-and-a-lambda-in-ruby)) or even define a separate ```class``` with an instance or class method (maybe even a ```module```) to return the currency code:
         
     | 
| 
       332 
332 
     | 
    
         | 
| 
         @@ -502,6 +502,7 @@ _For examples below, `@money_object == <Money fractional:650 currency:USD>`_ 
     | 
|
| 
       502 
502 
     | 
    
         
             
            | `humanized_money_with_symbol @money_object`           | $6.50                                     |
         
     | 
| 
       503 
503 
     | 
    
         
             
            | `money_without_cents @money_object`                   | 6                                         |
         
     | 
| 
       504 
504 
     | 
    
         
             
            | `money_without_cents_and_with_symbol @money_object`   | $6                                        |
         
     | 
| 
      
 505 
     | 
    
         
            +
            | `money_only_cents @money_object`                      | 50                                        |
         
     | 
| 
       505 
506 
     | 
    
         | 
| 
       506 
507 
     | 
    
         
             
            #### `no_cents_if_whole`
         
     | 
| 
       507 
508 
     | 
    
         | 
| 
         @@ -552,7 +553,7 @@ For examples on using the test_helpers look at 
     | 
|
| 
       552 
553 
     | 
    
         
             
            ## Supported ORMs/ODMs
         
     | 
| 
       553 
554 
     | 
    
         | 
| 
       554 
555 
     | 
    
         
             
            * ActiveRecord (>= 3.x)
         
     | 
| 
       555 
     | 
    
         
            -
            * Mongoid (2.x 
     | 
| 
      
 556 
     | 
    
         
            +
            * Mongoid (>= 2.x)
         
     | 
| 
       556 
557 
     | 
    
         | 
| 
       557 
558 
     | 
    
         
             
            ## Supported Ruby interpreters
         
     | 
| 
       558 
559 
     | 
    
         | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -13,6 +13,7 @@ rescue Bundler::BundlerError => e 
     | 
|
| 
       13 
13 
     | 
    
         
             
            end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
         
     | 
| 
      
 16 
     | 
    
         
            +
            GEMFILES_PATH = 'gemfiles/*.gemfile'.freeze
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
18 
     | 
    
         
             
            load 'rails/tasks/engine.rake' if File.exist?(APP_RAKEFILE)
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
         @@ -47,46 +48,27 @@ def run_with_gemfile(gemfile) 
     | 
|
| 
       47 
48 
     | 
    
         
             
            end
         
     | 
| 
       48 
49 
     | 
    
         | 
| 
       49 
50 
     | 
    
         
             
            namespace :spec do
         
     | 
| 
      
 51 
     | 
    
         
            +
              frameworks_versions = {}
         
     | 
| 
       50 
52 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
               
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
      
 53 
     | 
    
         
            +
              Dir[GEMFILES_PATH].each do |gemfile|
         
     | 
| 
      
 54 
     | 
    
         
            +
                file_name = File.basename(gemfile, '.gemfile')
         
     | 
| 
      
 55 
     | 
    
         
            +
                framework, version = file_name.split(/(\d+)/)
         
     | 
| 
      
 56 
     | 
    
         
            +
                major, minor = version.split(//)
         
     | 
| 
       53 
57 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                frameworks_versions[framework] ||= []
         
     | 
| 
      
 59 
     | 
    
         
            +
                frameworks_versions[framework] << file_name
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
              desc "Run Tests against mongoid (version 2)"
         
     | 
| 
       61 
     | 
    
         
            -
              task(:mongoid2) { run_with_gemfile 'gemfiles/mongoid2.gemfile' }
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
              desc "Run Tests against rails 5.1"
         
     | 
| 
       64 
     | 
    
         
            -
              task(:rails51) { run_with_gemfile 'gemfiles/rails51.gemfile' }
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
              desc "Run Tests against rails 5.0"
         
     | 
| 
       67 
     | 
    
         
            -
              task(:rails50) { run_with_gemfile 'gemfiles/rails50.gemfile' }
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
              desc "Run Tests against rails 4.2"
         
     | 
| 
       70 
     | 
    
         
            -
              task(:rails42) { run_with_gemfile 'gemfiles/rails42.gemfile' }
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
              desc "Run Tests against rails 4.1"
         
     | 
| 
       73 
     | 
    
         
            -
              task(:rails41) { run_with_gemfile 'gemfiles/rails41.gemfile' }
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
              desc "Run Tests against rails 4"
         
     | 
| 
       76 
     | 
    
         
            -
              task(:rails4) { run_with_gemfile 'gemfiles/rails4.gemfile' }
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
              desc "Run Tests against rails 3"
         
     | 
| 
       79 
     | 
    
         
            -
              task(:rails3) { run_with_gemfile 'gemfiles/rails3.gemfile' }
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
              desc "Run Tests against mongoid 2 & 3 & 4, 5"
         
     | 
| 
       82 
     | 
    
         
            -
              task mongoid: [:mongoid2, :mongoid3, :mongoid4, :mongoid5]
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
              desc "Run Tests against rails 3 & 4 & 4.1 & 4.2 & 5.0"
         
     | 
| 
       85 
     | 
    
         
            -
              task rails: [:rails3, :rails4, :rails41, :rails42, :rails50, :rails51]
         
     | 
| 
      
 61 
     | 
    
         
            +
                desc "Run Tests against #{framework} #{[major, minor].compact.join('.')}"
         
     | 
| 
      
 62 
     | 
    
         
            +
                task(file_name) { run_with_gemfile gemfile }
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
       86 
64 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
               
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
      
 65 
     | 
    
         
            +
              frameworks_versions.each do |framework, versions|
         
     | 
| 
      
 66 
     | 
    
         
            +
                desc "Run Tests against all supported #{framework} versions"
         
     | 
| 
      
 67 
     | 
    
         
            +
                task framework => versions
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
       89 
69 
     | 
    
         | 
| 
      
 70 
     | 
    
         
            +
              desc 'Run Tests against all ORMs'
         
     | 
| 
      
 71 
     | 
    
         
            +
              task all: frameworks_versions.keys
         
     | 
| 
       90 
72 
     | 
    
         
             
            end
         
     | 
| 
       91 
73 
     | 
    
         | 
| 
       92 
74 
     | 
    
         
             
            desc "Update CONTRIBUTORS file"
         
     | 
| 
         @@ -83,6 +83,29 @@ MoneyRails.configure do |config| 
     | 
|
| 
       83 
83 
     | 
    
         
             
              #   sign_before_symbol: nil
         
     | 
| 
       84 
84 
     | 
    
         
             
              # }
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
              # If you would like to use I18n localization (formatting depends on the
         
     | 
| 
      
 87 
     | 
    
         
            +
              # locale):
         
     | 
| 
      
 88 
     | 
    
         
            +
              # config.locale_backend = :i18n
         
     | 
| 
      
 89 
     | 
    
         
            +
              #
         
     | 
| 
      
 90 
     | 
    
         
            +
              # Example (using default localization from rails-i18n):
         
     | 
| 
      
 91 
     | 
    
         
            +
              #
         
     | 
| 
      
 92 
     | 
    
         
            +
              # I18n.locale = :en
         
     | 
| 
      
 93 
     | 
    
         
            +
              # Money.new(10_000_00, 'USD').format # => $10,000.00
         
     | 
| 
      
 94 
     | 
    
         
            +
              # I18n.locale = :es
         
     | 
| 
      
 95 
     | 
    
         
            +
              # Money.new(10_000_00, 'USD').format # => $10.000,00
         
     | 
| 
      
 96 
     | 
    
         
            +
              #
         
     | 
| 
      
 97 
     | 
    
         
            +
              # For the legacy behaviour of "per currency" localization (formatting depends
         
     | 
| 
      
 98 
     | 
    
         
            +
              # only on currency):
         
     | 
| 
      
 99 
     | 
    
         
            +
              # config.locale_backend = :currency
         
     | 
| 
      
 100 
     | 
    
         
            +
              #
         
     | 
| 
      
 101 
     | 
    
         
            +
              # Example:
         
     | 
| 
      
 102 
     | 
    
         
            +
              # Money.new(10_000_00, 'USD').format # => $10,000.00
         
     | 
| 
      
 103 
     | 
    
         
            +
              # Money.new(10_000_00, 'EUR').format # => €10.000,00
         
     | 
| 
      
 104 
     | 
    
         
            +
              #
         
     | 
| 
      
 105 
     | 
    
         
            +
              # In case you don't need localization and would like to use default values
         
     | 
| 
      
 106 
     | 
    
         
            +
              # (can be redefined using config.default_format):
         
     | 
| 
      
 107 
     | 
    
         
            +
              # config.locale_backend = nil
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
       86 
109 
     | 
    
         
             
              # Set default raise_error_on_money_parsing option
         
     | 
| 
       87 
110 
     | 
    
         
             
              # It will be raise error if assigned different currency
         
     | 
| 
       88 
111 
     | 
    
         
             
              # The default value is false
         
     | 
| 
         @@ -1,113 +1,108 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module MoneyRails
         
     | 
| 
       2 
2 
     | 
    
         
             
              module ActiveModel
         
     | 
| 
       3 
3 
     | 
    
         
             
                class MoneyValidator < ::ActiveModel::Validations::NumericalityValidator
         
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
       5 
     | 
    
         
            -
                     
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
      
 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 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def decimal_pieces
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @decimal_pieces ||= abs_raw_value.split(decimal_mark)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
       8 
13 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 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 = :"#{ 
     | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
      
 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  
     | 
| 
       19 
     | 
    
         
            -
                      subunit_value =  
     | 
| 
       20 
     | 
    
         
            -
                       
     | 
| 
      
 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] &&  
     | 
| 
      
 30 
     | 
    
         
            +
                    return if options[:allow_nil] && raw_value.nil?
         
     | 
| 
       24 
31 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                    # Set this before we modify  
     | 
| 
       26 
     | 
    
         
            -
                    stringy =  
     | 
| 
      
 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 
     | 
    
         
            -
                       
     | 
| 
      
 41 
     | 
    
         
            +
                      raw_value = raw_value.to_s.gsub(symbol, "")
         
     | 
| 
       31 
42 
     | 
    
         
             
                    end
         
     | 
| 
       32 
43 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                     
     | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                     
     | 
| 
       37 
     | 
    
         
            -
                      add_error if
         
     | 
| 
       38 
     | 
    
         
            -
                        value_has_too_many_decimal_points ||
         
     | 
| 
       39 
     | 
    
         
            -
                        thousand_separator_after_decimal_mark ||
         
     | 
| 
       40 
     | 
    
         
            -
                        invalid_thousands_separation
         
     | 
| 
       41 
     | 
    
         
            -
                    end
         
     | 
| 
       42 
     | 
    
         
            -
                  end
         
     | 
| 
      
 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)
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 49 
     | 
    
         
            +
                    super(record, attr, normalized_raw_value)
         
     | 
| 
       45 
50 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                    return  
     | 
| 
       48 
     | 
    
         
            -
                    !@record.errors.added?(@attr, :not_a_number)
         
     | 
| 
       49 
     | 
    
         
            -
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    return unless stringy
         
     | 
| 
      
 52 
     | 
    
         
            +
                    return if record_already_has_error?(record, attr, normalized_raw_value)
         
     | 
| 
       50 
53 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                       
     | 
| 
       54 
     | 
    
         
            -
                       
     | 
| 
       55 
     | 
    
         
            -
                      remove_instance_variable(ivar_name) if instance_variable_defined?(ivar_name)
         
     | 
| 
       56 
     | 
    
         
            -
                    end
         
     | 
| 
      
 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)
         
     | 
| 
       57 
58 
     | 
    
         
             
                  end
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
       60 
     | 
    
         
            -
                    @_currency ||= @record.public_send("currency_for_#{@attr}")
         
     | 
| 
       61 
     | 
    
         
            -
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  private
         
     | 
| 
       62 
61 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
                   
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
       65 
     | 
    
         
            -
                     
     | 
| 
       66 
     | 
    
         
            -
                   
     | 
| 
      
 62 
     | 
    
         
            +
                  DEFAULTS = {
         
     | 
| 
      
 63 
     | 
    
         
            +
                    decimal_mark: '.',
         
     | 
| 
      
 64 
     | 
    
         
            +
                    thousands_separator: ','
         
     | 
| 
      
 65 
     | 
    
         
            +
                  }.freeze
         
     | 
| 
       67 
66 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                  def  
     | 
| 
       69 
     | 
    
         
            -
                     
     | 
| 
       70 
     | 
    
         
            -
                     
     | 
| 
       71 
     | 
    
         
            -
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  def generate_details(raw_value, currency)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    thousands_separator = lookup(:thousands_separator, currency)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    decimal_mark = lookup(:decimal_mark, currency)
         
     | 
| 
       72 
70 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                    @_symbol ||= Money.use_i18n ? I18n.t('number.currency.format.unit', default: currency.symbol) : currency.symbol
         
     | 
| 
      
 71 
     | 
    
         
            +
                    Details.new(raw_value, thousands_separator, decimal_mark)
         
     | 
| 
       75 
72 
     | 
    
         
             
                  end
         
     | 
| 
       76 
73 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                  def  
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
      
 74 
     | 
    
         
            +
                  def record_already_has_error?(record, attr, raw_value)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    record.errors.added?(attr, :not_a_number, value: raw_value)
         
     | 
| 
       79 
76 
     | 
    
         
             
                  end
         
     | 
| 
       80 
77 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
                  def add_error
         
     | 
| 
       82 
     | 
    
         
            -
                    attr_name =  
     | 
| 
       83 
     | 
    
         
            -
                    attr_name =  
     | 
| 
      
 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)
         
     | 
| 
       84 
81 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
                     
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            +
                    })
         
     | 
| 
       90 
88 
     | 
    
         
             
                  end
         
     | 
| 
       91 
89 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
                  def  
     | 
| 
       93 
     | 
    
         
            -
                     
     | 
| 
      
 90 
     | 
    
         
            +
                  def value_has_too_many_decimal_points(details)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    ![1, 2].include?(details.decimal_pieces.length)
         
     | 
| 
       94 
92 
     | 
    
         
             
                  end
         
     | 
| 
       95 
93 
     | 
    
         | 
| 
       96 
     | 
    
         
            -
                  def  
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
      
 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)
         
     | 
| 
       98 
98 
     | 
    
         
             
                  end
         
     | 
| 
       99 
99 
     | 
    
         | 
| 
       100 
     | 
    
         
            -
                  def  
     | 
| 
       101 
     | 
    
         
            -
                     
     | 
| 
       102 
     | 
    
         
            -
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  def invalid_thousands_separation(details)
         
     | 
| 
      
 101 
     | 
    
         
            +
                    pieces_array = details.decimal_pieces[0].split(details.thousands_separator.presence)
         
     | 
| 
       103 
102 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
                  def thousand_separator_after_decimal_mark
         
     | 
| 
       105 
     | 
    
         
            -
                    thousands_separator.present? && decimal_pieces.length == 2 && decimal_pieces[1].include?(thousands_separator)
         
     | 
| 
       106 
     | 
    
         
            -
                  end
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                  def invalid_thousands_separation
         
     | 
| 
       109 
103 
     | 
    
         
             
                    return false if pieces_array.length <= 1
         
     | 
| 
       110 
104 
     | 
    
         
             
                    return true  if pieces_array[0].length > 3
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
       111 
106 
     | 
    
         
             
                    pieces_array[1..-1].any? do |thousands_group|
         
     | 
| 
       112 
107 
     | 
    
         
             
                      thousands_group.length != 3
         
     | 
| 
       113 
108 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -115,16 +110,25 @@ module MoneyRails 
     | 
|
| 
       115 
110 
     | 
    
         | 
| 
       116 
111 
     | 
    
         
             
                  # Remove thousands separators, normalize decimal mark,
         
     | 
| 
       117 
112 
     | 
    
         
             
                  # remove whitespaces and _ (E.g. 99 999 999 or 12_300_200.20)
         
     | 
| 
       118 
     | 
    
         
            -
                  def  
     | 
| 
       119 
     | 
    
         
            -
                     
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
                    @raw_value = @raw_value.to_s
         
     | 
| 
       124 
     | 
    
         
            -
                      .gsub(thousands_separator, '')
         
     | 
| 
       125 
     | 
    
         
            -
                      .gsub(decimal_mark, '.')
         
     | 
| 
      
 113 
     | 
    
         
            +
                  def normalize(details)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    details.raw_value
         
     | 
| 
      
 115 
     | 
    
         
            +
                      .to_s
         
     | 
| 
      
 116 
     | 
    
         
            +
                      .gsub(details.thousands_separator, '')
         
     | 
| 
      
 117 
     | 
    
         
            +
                      .gsub(details.decimal_mark, '.')
         
     | 
| 
       126 
118 
     | 
    
         
             
                      .gsub(/[\s_]/, '')
         
     | 
| 
       127 
119 
     | 
    
         
             
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                  def lookup(key, currency)
         
     | 
| 
      
 122 
     | 
    
         
            +
                    if locale_backend
         
     | 
| 
      
 123 
     | 
    
         
            +
                      locale_backend.lookup(key, currency) || DEFAULTS[key]
         
     | 
| 
      
 124 
     | 
    
         
            +
                    else
         
     | 
| 
      
 125 
     | 
    
         
            +
                      DEFAULTS[key]
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  def locale_backend
         
     | 
| 
      
 130 
     | 
    
         
            +
                    Money.locale_backend
         
     | 
| 
      
 131 
     | 
    
         
            +
                  end
         
     | 
| 
       128 
132 
     | 
    
         
             
                end
         
     | 
| 
       129 
133 
     | 
    
         
             
              end
         
     | 
| 
       130 
134 
     | 
    
         
             
            end
         
     | 
| 
         @@ -11,8 +11,8 @@ module MoneyRails 
     | 
|
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                    def remove_monetize(table_name, accessor, options={})
         
     | 
| 
       13 
13 
     | 
    
         
             
                      [:amount, :currency].each do |attribute|
         
     | 
| 
       14 
     | 
    
         
            -
                        column_present, table_name, column_name,  
     | 
| 
       15 
     | 
    
         
            -
                        remove_column table_name, column_name if column_present
         
     | 
| 
      
 14 
     | 
    
         
            +
                        column_present, table_name, column_name, type, _ =  OptionsExtractor.extract attribute, table_name, accessor, options
         
     | 
| 
      
 15 
     | 
    
         
            +
                        remove_column table_name, column_name, type if column_present
         
     | 
| 
       16 
16 
     | 
    
         
             
                      end
         
     | 
| 
       17 
17 
     | 
    
         
             
                    end
         
     | 
| 
       18 
18 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -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 
     | 
| 
      
 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
         
     | 
| 
         @@ -7,7 +7,6 @@ module MoneyRails 
     | 
|
| 
       7 
7 
     | 
    
         
             
              # MoneyRails configuration module.
         
     | 
| 
       8 
8 
     | 
    
         
             
              # This is extended by MoneyRails to provide configuration settings.
         
     | 
| 
       9 
9 
     | 
    
         
             
              module Configuration
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
10 
     | 
    
         
             
                # Start a MoneyRails configuration block in an initializer.
         
     | 
| 
       12 
11 
     | 
    
         
             
                #
         
     | 
| 
       13 
12 
     | 
    
         
             
                # example: Provide a default currency for the application
         
     | 
| 
         @@ -59,7 +58,7 @@ module MoneyRails 
     | 
|
| 
       59 
58 
     | 
    
         
             
                #   MoneyRails.configure do |config|
         
     | 
| 
       60 
59 
     | 
    
         
             
                #     config.default_bank = EuCentralBank.new
         
     | 
| 
       61 
60 
     | 
    
         
             
                #   end
         
     | 
| 
       62 
     | 
    
         
            -
                delegate :default_bank=, :default_bank, to: :Money
         
     | 
| 
      
 61 
     | 
    
         
            +
                delegate :default_bank=, :default_bank, :locale_backend, :locale_backend=, to: :Money
         
     | 
| 
       63 
62 
     | 
    
         | 
| 
       64 
63 
     | 
    
         
             
                # Provide exchange rates
         
     | 
| 
       65 
64 
     | 
    
         
             
                delegate :add_rate, to: :Money
         
     |