Rails: money gem converts all amounts to zero

后端 未结 2 1756
醉梦人生
醉梦人生 2020-12-24 09:30

I\'m trying to use the money gem to handle currency in my app but I\'m running into a strange error. This is what I have in my \"record\" model:

composed_of          


        
2条回答
  •  情书的邮戳
    2020-12-24 10:17

    EDIT: Added Bonus at the end of the answer

    Well, your question was interesting to me so I decided to try myself.

    This works properly:

    1) Product migration:

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

    2) Product model

    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:

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

    4) Products Helper (handmade):

    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
    

    BONUS:

    If you want to add currency exchange rates:

    1) Your gemfile

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

    2) Initializer

    create money.rb in you initializers folder and put this inside:

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

    reboot your server

    3) Play!

    Wherever you are, you can exchange the money.

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

    Display with nice rendering:

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

提交回复
热议问题