Rails:money gem将所有金额转换为零

时间:2011-01-25 20:49:59

标签: ruby-on-rails ruby ruby-on-rails-3 rubygems currency

我正在尝试使用money gem处理我的应用中的货币,但我遇到了一个奇怪的错误。这就是我在“记录”模型中所拥有的:

composed_of :amount,
            :class_name => "Money",
            :mapping => [%w(cents cents), %w(currency currency_as_string)],
            :constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
            :converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }

金额是整数。

当我创建一个新记录时,它会忽略我在amount字段中输入的任何值,并将其默认为0.我需要在表单中添加一些内容吗?

我使用的是rails 3.0.3,而money gem版本是3.5.5

2 个答案:

答案 0 :(得分:22)

编辑:在答案结尾处添加了奖励

嗯,你的问题对我来说很有趣,所以我决定尝试自己。

这很正常:

1)产品迁移:

create_table :products do |t|
  t.string :name
  t.integer :cents, :default => 0
  t.string :currency
  t.timestamps
end

2)产品型号

class Product < ActiveRecord::Base

   attr_accessible :name, :cents, :currency

  composed_of :price,
    :class_name => "Money",
    :mapping => [%w(cents cents), %w(currency currency_as_string)],
    :constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
    :converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
end

3)表格:

<%= form_for(@product) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %> 
  </div>
  <div class="field">
    <%= f.label :cents %><br />
    <%= f.text_field :cents %>
  </div>
  <div class="field">
    <%= f.label :currency %><br />      
   <%= f.select(:currency,all_currencies(Money::Currency::TABLE), {:include_blank => 'Select a Currency'}) %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

4)产品助手(手工制作):

module ProductsHelper
  def major_currencies(hash)
    hash.inject([]) do |array, (id, attributes)|
      priority = attributes[:priority]
      if priority && priority < 10
        array ||= []
        array << [attributes[:name], attributes[:iso_code]]
      end
      array
    end
  end

  def all_currencies(hash)
    hash.inject([]) do |array, (id, attributes)|
      array ||= []
      array << [attributes[:name], attributes[:iso_code]]
      array
    end
  end
end

奖金:

如果您想添加货币汇率:

1)你的宝石文件

gem 'json' #important, was not set as a dependency, so I add it manually
gem 'google_currency'

2)初始化程序

在你的初始化文件夹中创建money.rb并将其放入:

require 'money'
require 'money/bank/google_currency'
Money.default_bank = Money::Bank::GoogleCurrency.new

重启服务器

3)玩!

无论你在哪里,都可以换钱。

Product.first.price.exchange_to('USD')

显示精美渲染:

Product.first.price.format(:symbol => true)

答案 1 :(得分:1)

tl; dr:将:金额更改为:价格:anything_else

我的结论是:金额是在money gem中使用的关键字,因此在您的应用程序中使用它会导致问题。

这是一个延伸,但作者使用文档第一行中的金额来描述它的作用。

“提供Money类,其中包含有关某些金额金钱的所有信息,例如其价值和货币。” http://money.rubyforge.org/

在我的Rails 3.0项目中,我有3个非常相似的模型来扩展金钱类:人工,零件和付款。

人工和零件使用:price 属性工作正常,但我想在我的付款模式中使用:金额,因为在大声朗读或在我的笔记中听起来更好头。

我遇到的问题是,Payment会接受有效的表单输入,抛出:amount ,在数据库中保存0,并为nil抛出未定义的方法`round':NilClass 错误,查看记录后:

我很确定0是我的迁移选项转换为nil的症状(:null =&gt; false,默认=&gt; 0)。我通过使用safari web检查器调试View,然后通过提升和检查每个变量来控制Controller。模型中的这类问题没有多大意义,所以我认为它必须是金钱。然后,我找到了这个帖子,并把它们放在一起。

在回滚迁移并将所有:金额引用更改为:价格后,它可以正常运行。

我知道这个帖子已经有几个月了,但希望这有助于其他人在将来避免这个陷阱。

与此同时,我会坚持:价格