【问题标题】:money-rails, Money#== supports only zero numericsmoney-rails, Money#== 仅支持零数字
【发布时间】:2019-02-20 05:44:58
【问题描述】:

我在我的 Rails 应用程序中使用 money-rails gem。到目前为止,它一直运行良好,但我最近开始收到以下错误:

Money#== supports only zero numerics

我不确定是什么原因造成的,也不知道如何解决。我最近运行了bundle update,所以我猜有些东西已经更新了。我的gemfile 看起来像这样:

gem 'money-rails', '~>1'
gem 'eu_central_bank', "~>1.3.0"

我的实现如下所示:

# model
monetize :price_in_cents

# fetch / converting currencies
eu_bank = EuCentralBank.new
Money.default_bank = eu_bank
eu_bank.update_rates
converted_price = eu_bank.exchange_with(Money.new(price_to_convert * 100, from_currency), to_currency)

正如我之前提到的那样,这已经奏效了,所以我不确定是什么破坏了它。

有什么想法吗?

更新

为了测试我尝试了以下方法。

money = Money.new(100, from_currency)

然后我得到了和以前一样的错误。但如果我尝试过:

money = Money.new(0, from_currency)

它似乎工作。我觉得这有点奇怪。

更新

这是我尝试保存记录时的回溯:

["/Users/[user]/.rvm/gems/ruby-2.5.1/gems/money-6.11.3/lib/money/money/arithmetic.rb:70:in =='", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations/numericality.rb:22:in!=' ", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations/numericality.rb:22:in validate_each'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validator.rb:150:inblock in validate'" , "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validator.rb:147:in each'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validator.rb:147:invalidate'", "/Users/ [用户]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:413:in block in make_lambda'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:197:inblock (2 级) inhalting'", "/Users /[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:601:in block (2 levels) in default_terminator'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:600:incatch'", "/Users/[user]/ .rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:600:in block in default_terminator'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:198:inblock inhalting'", "/Users/[user]/.rvm/ gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507:in block in invoke_before'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507:ineach'", "/Users/[user]/.rvm/gems/ruby-2.5 .1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507:in invoke_before'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:130:inrun_c allbacks'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:827:in _run_validate_callbacks'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations.rb:405:inrun_validations!'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations/callbacks.rb:114:in block in run_validations!'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:97:inrun_callbacks'", "/Users /[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:827:in _run_validation_callbacks'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations/callbacks.rb:114:inrun_validations!'", "/Users/[user] /.rvm/gems/ruby-2.5.1/gems/activemodel-5.1.6/lib/active_model/validations.rb:335:in valid?'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/validations.rb:65:invalid?'", "/Users/[user]/.rvm/ gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/validations.rb:82:in perform_validations'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/validations.rb:50:insave!'", "/Users/[user]/.rvm/gems/ruby- 2.5.1/gems/activerecord-5.1.6/lib/active_record/attribute_methods/dirty.rb:43:in save!'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/transactions.rb:313:inblock in save!'", "/Users/[user]/.rvm/gems/ruby- 2.5.1/gems/activerecord-5.1.6/lib/active_record/transactions.rb:384:in block in with_transaction_returning_status'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/connection_adapters/abstract/database_statements.rb:235:inblock in transaction'", "/Users/[user]/.rvm/gems/ruby-2.5.1 /gems/activerecord-5.1.6/lib/active_recor d/connection_adapters/abstract/transaction.rb:194:in block in within_new_transaction'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/monitor.rb:226:inmon_synchronize'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record /connection_adapters/abstract/transaction.rb:191:in within_new_transaction'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/connection_adapters/abstract/database_statements.rb:235:intransaction'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/ transactions.rb:210:in transaction'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/transactions.rb:381:inwith_transaction_returning_status'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/transactions.rb:313 :in save!'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activerecord-5.1.6/lib/active_record/suppressor.rb:46:insave!'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:245:in block in set_supported_currencys_for_product_variant'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:240:ineach'", "/Users/ [user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:240:in set_supported_currencys_for_product_variant'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:224:inset_up_product_variant'", "/Users/[user]/Documents/Development/wondery/[appname]/ lib/importers/bts_wholesaler_importer.rb:208:in match_product_variant_to_product'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:84:inblock in get_products_from_api_data'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_whol esaler_importer.rb:75:in map'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:75:inget_products_from_api_data'", "/Users/[user]/Documents/Development/wondery/[appname]/lib/importers/bts_wholesaler_importer.rb:25:in import'", "(irb):2:inirb_binding'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:in eval'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:inevaluate'", "/Users/[user] /.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb/context.rb:380:in evaluate'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:491:inblock (2 个级别) in eval_input'", "/Users/[user]/ .rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:623:in signal_status'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:488:inblock in eval_input'", "/Users/[user]/.rvm/rubies/ruby- 2.5.1/lib/ruby/2.5.0/irb/ruby-lex.rb:246:in block (2 levels) in each_top_level_statement'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb/ruby-lex.rb:232:inloop'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib /ruby/2.5.0/irb/ruby-lex.rb:232:in block in each_top_level_statement'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb/ruby-lex.rb:231:incatch'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5. 0/irb/ruby-lex.rb:231:in each_top_level_statement'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:487:ineval_input'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb :428:in block in run'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:427:incatch'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:427:in run'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/irb.rb:383:instart' ", "/用户/[用户]/.rvm/ gems/ruby-2.5.1/gems/railties-5.1.6/lib/rails/commands/console/console_command.rb:62:in start'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/railties-5.1.6/lib/rails/commands/console/console_command.rb:17:instart'", "/Users/[user]/.rvm/gems /ruby-2.5.1/gems/railties-5.1.6/lib/rails/commands/console/console_command.rb:97:in perform'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/thor-0.20.0/lib/thor/command.rb:27:inrun'", "/Users/[user]/.rvm/gems/ ruby-2.5.1/gems/thor-0.20.0/lib/thor/invocation.rb:126:in invoke_command'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/thor-0.20.0/lib/thor.rb:387:indispatch'", "/Users/[user]/.rvm/gems/ruby-2.5.1 /gems/railties-5.1.6/lib/rails/command/base.rb:63:in perform'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/railties-5.1.6/lib/rails/command.rb:44:ininvoke'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/ railties-5.1.6/lib/rails/commands.rb:16:in <top (required)>'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:292:inrequire'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6 /lib/active_support/dependencies.rb:292:in block in require'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:258:inload_dependency'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/ dependencies.rb:292:in require'", "/Users/[user]/Documents/Development/wondery/[appname]/bin/rails:9:in'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:286:在load'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:286:inblock in load'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/li b/active_support/dependencies.rb:258:in load_dependency'", "/Users/[user]/.rvm/gems/ruby-2.5.1/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:286:inload'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/site_ruby/2.5.0/rubygems/core_ext /kernel_require.rb:59:in require'", "/Users/[user]/.rvm/rubies/ruby-2.5.1/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:inrequire'", "-e:1:in `'"]

【问题讨论】:

  • 您是否使用代码版本控制,例如 git?如果是,您应该能够比较您的 Gemfile.lock 以查看版本是否以及如何更新。有了这些信息,您应该能够找出所涉及的两个 gem 中的任何一个发生了什么变化,并可能找到出错的提示......否则,如果您不想或不需要更新,您可以恢复到以前的版本,通过在您的 Gemfile 中指定确切的版本,您可以从工作版本继续前进。
  • 一般来说,我不建议您运行“捆绑更新”,尤其是如果您将 gem 锁定为市长版本,例如 '~>1' 的情况
  • 哦,你可以考虑在 gems github 页面上寻求帮助:github.com/RubyMoney/money-rails
  • 您可以在问题中包含回溯吗?这将有助于缩小问题的范围。虽然我根本不知道您的问题是什么,但我想您正试图以某种方式给 Money 的一部分浮动(如 100.05 美元),而不是整数美分(10005c)。您是否将数据库列声明为整数或浮点/双精度,因为如果数据库列数据类型不是 Money 所期望的,问题可能与 Rails 如何初始化内容有关。
  • @Nate 我现在已将完整的堆栈回溯添加到我的问题中。

标签: ruby-on-rails ruby currency money-rails


【解决方案1】:

Money Rails 会自动将“_cents”添加到您正在获利的属性中。然后它创建一个 model.price 的实例,其中包括

<Money fractional:1500 currency:DKK>

因此,您不能执行 model.price + 10,因为这会导致您遇到错误。 因此,您可能希望将 price_to_convert 或您正在使用的任何其他价值货币化,以便您可以总结它们等。

创建一个新的迁移文件,例如 rails g 迁移 AddMoneytizeToOrders

更改迁移文件,使其如下所示(将列/属性更改为您的值)

class AddMonetizeToOrder < ActiveRecord::Migration[6.0]
  def change
    add_monetize :orders, :price_to_convert, currency: { present: false }
  end
end

在您的模型中,您必须包含

monetize :price_to_convert_cents

然后您可以使用例如(rails c)Order.last.price_to_convert + Model.last.price 等。

请注意,您不能使用 self.[:price_to_convert] 因为money rails 无法理解它并且您会收到错误

money rails ActiveModel::MissingAttributeError (can't write unknown attribute...

因此改用 self.price_to_convert

【讨论】:

    【解决方案2】:

    您在编写规范时也可能遇到此错误:

    expect(order.subtotal).to eq 123.45
    # ArgumentError:
    #   Money#== supports only zero numerics
    
    expect(order.subtotal).to eq Money.new(12345)
    # works!
    

    【讨论】:

      【解决方案3】:

      错误来自模型的数值验证。

      Money gem 不允许将货币对象与数字进行比较,除非您的数字为零。否则,它希望您将 Money 与 Money 进行比较。

      在irb你可以试试:

      ```红宝石

      2.5.1 :006 > Money.new(1000, "USD") != Money.new(1000, "USD")
       => false 
      
      2.5.1 :007 > Money.new(1000, "USD") != 1000
      Traceback (most recent call last):
              4: from /Users/andi/.rvm/rubies/ruby-2.5.1/bin/irb:11:in `<main>'
              3: from (irb):7
              2: from (irb):7:in `!='
              1: from /Users/andi/.rvm/gems/ruby-2.5.1/gems/money-6.12.0/lib/money/money/arithmetic.rb:70:in `=='
      ArgumentError (Money#== supports only zero numerics)
      
      2.5.1 :008 > Money.new(1000, "USD") != 0
       => true 
      

      ```

      我相信这个错误是有道理的,因为您无法真正将任意数字与给定货币的金额进行比较。

      money-rails gem 再次带有它自己的验证器:

      https://github.com/RubyMoney/money-rails#numericality-validation-options

      您的回溯表明您正在使用 rails 数字验证器。

      【讨论】:

      • 谢谢。我跟着你的链接。禁用验证似乎有效。在保存对象之前我自己没有做任何比较,所以我还是觉得有点奇怪。
      • 它是在保存对象之前进行比较的数字验证器。这就是为什么money-rails gem 添加了他们自己的验证器,因为可能很多人想在他们的货币属性上使用验证器。
      猜你喜欢
      • 2015-08-29
      • 1970-01-01
      • 2015-07-20
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      相关资源
      最近更新 更多