【问题标题】:Rails: money gem converts all amounts to zeroRails:金钱宝石将所有金额转换为零
【发布时间】:2011-06-15 11:32:08
【问题描述】:

我正在尝试使用 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") }

金额是一个整数。

当我创建新记录时,它会忽略我在金额字段中输入的任何值并将其默认为 0。我需要在表单中添加什么吗?

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

【问题讨论】:

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


    【解决方案1】:

    编辑:在答案末尾添加奖励

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

    这可以正常工作:

    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 文件

    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)
    

    【讨论】:

    • 谢谢,我现在更了解宝石了。我需要将映射更改为 %w(amount cents)
    • 好消息,我今天在想,刚刚测试:价格列在迁移中没有用。我已经编辑了帖子。
    • +1 太棒了!一周以来,我一直在寻找有关金钱宝石的一些基本指导,但没有运气。不幸的是,在谷歌中搜索任何东西都会出现非常不可靠的结果:)
    • +1,你的这个答案应该在他们的 github 链接上......很好地解释了
    • 粉碎它。我是为设置货币而来的,并为谷歌货币而留下。谢谢。
    【解决方案2】:

    tl;dr:将 :amount 更改为 :price:anything_else

    我已经得出结论,:amount 是在货币宝石某处使用的关键字,因此在您的应用程序中使用它会导致问题。

    这是一个延伸,但作者使用文档第一行中的单词数量来描述它的作用。

    “提供了一个 Money 类,它封装了有关特定金额货币的所有信息,例如其价值和货币。” http://money.rubyforge.org/

    在我的 Rails 3.0 项目中,我有 3 个非常相似的模型来扩展货币类:Labor、Part 和 Payment。

    Labor 和 Part 使用属性 :price 可以正常工作,但我想在我的 Payment 模型中使用 :amount,因为它在大声朗读或在我的头。

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

    我很确定 0 是 nil 被我的迁移选项转换的症状(:null => false,默认 => 0)。我通过使用 safari web 检查器调试排除了视图,然后通过提升和检查每个变量来排除控制器。模型中的这种问题没有多大意义,所以我认为它必须是钱。然后,我找到了这个线程,并将它们放在一起。

    在回滚迁移并将所有 :amount 引用更改为 :price 后,它可以完美运行。

    我知道这个帖子有几个月的历史了,但希望这能帮助其他人在未来避免这个陷阱。

    与此同时,我将坚持 :price

    【讨论】:

    • 作为参考,今天使用“金额”对我有用;我尝试使用 Money 3.7.1 和 Rails 3.1,使用“美分”列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    相关资源
    最近更新 更多