Рельсы: денежный камень конвертирует все суммы в ноль - PullRequest
9 голосов
/ 25 января 2011

Я пытаюсь использовать денежный камень для обработки валюты в моем приложении, но я сталкиваюсь со странной ошибкой.Вот что я имею в своей «рекордной» модели:

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. Есть ли что-то, что мне нужно добавить к формам?3.0.3 и версия самоцвета 3.5.5

Ответы [ 2 ]

22 голосов
/ 26 января 2011

РЕДАКТИРОВАТЬ: Добавлен бонус в конце ответа

Ну, ваш вопрос был мне интересен, поэтому я решил попробовать себя.

Это работает правильно:

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) Продукция Helper (ручная работа):

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 голос
/ 23 августа 2011

tl; др: изменить : сумма на : цена или : что-нибудь еще .

Я пришел к выводу, что : сумма - это ключевое слово, используемое где-то в денежном сокровище, поэтому использование его в вашем приложении вызывает проблемы.

Это натянуто, но автор использует слово количество в первой строке документации, чтобы описать, что оно делает.

"Предоставляет класс Money, который инкапсулирует всю информацию об определенной сумме денег, такую ​​как ее стоимость и валюта." http://money.rubyforge.org/

В моем проекте Rails 3.0 у меня есть 3 очень похожих модели, которые расширяют класс денег: Труд, Часть и Оплата.

Работа и Part работают нормально с использованием атрибута : цена , но я хотел использовать : сумму в моей модели Payment, потому что она звучала лучше, когда я читал вслух или в моей голове.

Проблема, с которой я столкнулся, заключается в том, что Payment будет принимать действительные данные формы, выбрасывать : сумму , сохранять 0 в базе данных и выбрасывать неопределенный метод round для nil: NilClass ошибка при просмотре записи:

Я почти уверен, что 0 - это признак того, что nil конвертируется моими параметрами миграции (: null => false, default => 0). Я исключил представление, отладив его с помощью веб-инспектора safari, а затем Controller, подняв и проверив каждую переменную. Такая проблема в модели не имеет большого смысла, поэтому я решил, что это должны быть деньги. Затем я нашел эту ветку и соединил все вместе.

После отката миграции и изменения всех : сумма ссылается на : цена , она отлично работает.

Я знаю, что этой ветке несколько месяцев, но, надеюсь, это поможет кому-то еще избежать этой ловушки в будущем.

А пока я буду придерживаться : цена .

...