Как получить полную цену за драгоценный камень - PullRequest
3 голосов
/ 07 июня 2011

Я использую денежный камень , и я хотел бы узнать , как я могу получить цены, такие как 23,45, 10,00, 0,32, для отображения в одном поле как dollar.cents? Я хочу, чтобы моиполе центов, чтобы стать только Цена (деньги или доллары и центы).

Вот мой код:

Моя модель с жемчужиной денег состояла из:

class Price < ActiveRecord::Base
    attr_accessible :name, :date, :cents, :currency

    belongs_to :user

    validates :name,       :presence => true,
                           :length   => { :maximum => 50 }

    validates :currency,   :presence => true
    validates :cents,      :presence => true
    validates :date,       :presence => true

    default_scope :order => 'prices.created_at DESC'

    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

Форма (я вырезал части длякраткость):

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :date %><br />
    <%= f.date_select :date %>
  </div>
  <div class="field">
    <%= f.label :cents %><br />
    <%= f.text_field :cents %>
  </div>
  <><div class="field">
    <%= f.label :currency %><br />
    <%= f.select(:currency,major_currencies(Money::Currency::TABLE), 
    {:include_blank => 'Select a Currency'}) %>
  </div>

Моя таблица миграции или цен:

class CreatePrices < ActiveRecord::Migration
  def self.up
    create_table :prices do |t|
      t.integer :user_id
      t.string :name
      t.date :date
      t.integer :cents, :default => 0
      t.string :currency

Похоже, мне не хватает столбца или чего-то еще.Предполагается, что даже одни центы?Не уверен, поэтому мне нужна ваша помощь.

Спасибо, что нашли время.

Ответы [ 4 ]

4 голосов
/ 12 июня 2013

Просто столкнулся с точно такой же проблемой, и если вы не хотите менять свою БД, как вы это делали в выбранном вами ответе, просто взгляните на исходный код драгоценного камня, чтобы увидеть, есть ли что-нибудь, что вы можетеиспользуйте:

https://github.com/RubyMoney/money-rails/blob/master/lib/money-rails/helpers/action_view_extension.rb

В этом модуле вы заметите две вещи:

  1. Метод с именем humanize_money
  2. В этом методевызов формата метода для денежного объекта

Итак, просто вызовите @my_money_object.format, и .... bam, у вас есть формат денежного объекта в строкуС долларами и центами с точностью до 2.

Пример:

@my_money_object = 20.to_money
@my_money_object.format

=> "$ 20.00"

Это действительно правильное решение.Вы специально сказали, что «вы просто хотите получить полную цену, например, $ 45,23».Теперь, если вы хотите поместить эту отформатированную строку в вашу БД таким образом, это ваше дело, но я бы посоветовал просто вызвать метод format для денежного объекта, где это необходимо.Мне нужно было получить отформатированную цену в контроллере, и, очевидно, у меня не было доступа к методу humanize_money, если я не нахожусь в представлении (не пытаясь взломать дополнительный метод для этого), поэтому я проверил исходный код и нашелэтот.Проголосуйте, если это помогло вам.

1 голос
/ 07 июня 2011

Я скачал драгоценный камень и протестировал несколько вариантов. Следуя примерам https://github.com/RubyMoney/money, вы можете сделать:

money = Money.new(1000, "USD")
money.cents     #=> 1000
money.dollars   #=> 10.0

Так что, на мой взгляд, в вашей модели должен быть подобный метод. Цена:

def value
  cents / 100.0
end

И используйте его в представлениях (или там, где вам нужно значение в валюте, а не в центах). При добавлении цены вы делаете это в центах, таким образом, чтобы иметь цену 12,34, вы должны установить ее в 1234 цента. Если вы хотите добавить цену, например, 12,34, я думаю, вам следует проанализировать ее в контроллере (при создании / обновлении действия) или в модели с фильтром before_save или чем-то в этом роде. Просто умножьте его на 100, чтобы сохранить как центы в БД.

EDIT: вспомогательный метод для добавления нулей для просмотра.

def with_zeros(price)
  array = price.to_s.split('.')
  array[1] = array[1].ljust(2,'0')
  array.join('.')
end
1 голос
/ 07 июня 2011

Ну,

В вашей таблице БД вы держите центы как целые числа:

 t.integer :cents, :default => 0

Попробуйте изменить это на:

 t.decimal :cents, :default => 0
0 голосов
/ 08 июня 2011

Хорошо, я смог понять это, спасибо всем!

Вот мой новый код:

База данных теперь: цена вместо: центов -

create_table :prices do |t|
  t.integer :user_id
  t.string :name
  t.date :date
  t.integer :price, :default => 0
  t.string :currency

область формы:

  <div class="field">
    <%= f.label :price %><br />
    <%= f.text_field :price %>
  </div>

новое состав_ф:

composed_of :price,
    :class_name  => "Money",
    :mapping     => [%w(price 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 conver #{value.class} to Money") }

Мне просто нужно было сделать так, чтобы mixed_of соответствовал отображению , столбцу базы данных и форме , и по какой-то странной причине он начал работать полностью. Спасибо всем за помощь, я многое узнал о рубине и рельсах.

...