Rails: money gem конвертирует все суммы в ноль

Я пытаюсь использовать 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.


person David    schedule 25.01.2011    source источник


Ответы (2)


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

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

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

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)
person apneadiving    schedule 25.01.2011
comment
Спасибо, теперь я понимаю драгоценный камень намного лучше. Мне нужно было изменить сопоставление на %w(количество центов) - person David; 26.01.2011
comment
Хорошие новости, я сегодня думал и только что проверил: столбец цены бесполезен в миграции. Я отредактировал сообщение. - person apneadiving; 26.01.2011
comment
+1 Потрясающе! Я безуспешно искал какое-то базовое руководство по денежному камню в течение недели. К сожалению, поиск чего-либо Money в Google дает очень сомнительные результаты :) - person mhenrixon; 30.01.2011
comment
+1, ваш этот ответ должен быть по их ссылке на github ... хорошо объяснено - person Anidhya Ahuja; 07.11.2011
comment
Раздавил его. Я пришел за настройкой денег, а остался за валютой гугла. Спасибо. - person Joshua Pinter; 15.01.2012

tl;dr: измените :amount на :price или :anything_else.

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

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

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

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

Труд и часть прекрасно работают с использованием атрибута :price, но я хотел использовать :amount в своей модели оплаты, потому что это звучало лучше при чтении вслух или про себя.

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

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

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

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

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

person James Dunn    schedule 23.08.2011
comment
Для справки, сегодня мне помогло использование «количества»; Я пробовал с Money 3.7.1 и Rails 3.1, используя столбец «центы». - person Thibaut Barrère; 07.09.2011