18

ユーザーがフォームに数値を入力するときに小数点またはコンマを使用できるようにするための最適な Ruby/Rails の方法は何ですか? つまり、ユーザーが 2,000.99 を入力できるようにして、データベースで 2.00 を取得できないようにしたいと考えています。

これに対するベストプラクティスはありますか?

- アップデート - -

gsub は float または biginteger で動作しますか? または、float や int をフォームに入力すると、Rails は自動的に , で数字を切り捨てますか? self.price.gsub(",", "") を使用してみましたが、「8:Fixnum の未定義メソッド `gsub'」が表示されます。ここで、8 はフォームに入力した数字です。

4

8 に答える 8

27

フォーム内でローカライズされたコンテンツを使用しようとすると、同様の問題が発生しました。出力ActionView::Helpers::NumberHelperのローカライズは組み込みメソッドを使用すると比較的簡単ですが、ローカライズされた入力の解析は ではサポートされていませんActiveRecord

これが私の解決策です。何か間違っていることがあれば教えてください。正しい解決策であるには単純すぎるように思えます。ありがとう!:)

まず、 にメソッドを追加しましょうString

class String
  def to_delocalized_decimal
    delimiter = I18n::t('number.format.delimiter')
    separator = I18n::t('number.format.separator')
    self.gsub(/[#{delimiter}#{separator}]/, delimiter => '', separator => '.')
  end
end

次に、クラスメソッドを追加しましょうActiveRecord::Base

class ActiveRecord::Base
  def self.attr_localized(*fields)
    fields.each do |field|
      define_method("#{field}=") do |value|
        self[field] = value.is_a?(String) ? value.to_delocalized_decimal : value
      end
    end
  end
end

最後に、入力をローカライズする必要があるフィールドを宣言しましょう。

class Article < ActiveRecord::Base
  attr_localized :price
end

ここで、フォームに「1.936,27」と入力するActiveRecordと、1936.27 になるため、無効な番号でエラーが発生することはありません。

于 2013-02-19T15:51:38.630 に答える
10

これは、数年前にGreg Brown ( Ruby Best Practicesの著者) からコピーしたコードです。モデルでは、どの項目が「ヒト化」されているかを識別します。

class LineItem < ActiveRecord::Base
  humanized_integer_accessor :quantity
  humanized_money_accessor :price
end

ビュー テンプレートでは、人間化されたフィールドを参照する必要があります。

= form_for @line_item do |f|
  Price:
  = f.text_field :price_humanized

これは、次の要因によって推進されます。

class ActiveRecord::Base
  def self.humanized_integer_accessor(*fields)
    fields.each do |f|
      define_method("#{f}_humanized") do
        val = read_attribute(f)
        val ? val.to_i.with_commas : nil
      end
      define_method("#{f}_humanized=") do |e|
        write_attribute(f,e.to_s.delete(","))
      end
    end
  end

  def self.humanized_float_accessor(*fields)
    fields.each do |f|
      define_method("#{f}_humanized") do
        val = read_attribute(f)
        val ? val.to_f.with_commas : nil
      end
      define_method("#{f}_humanized=") do |e|
        write_attribute(f,e.to_s.delete(","))
      end
    end
  end

  def self.humanized_money_accessor(*fields)
    fields.each do |f|
      define_method("#{f}_humanized") do
        val = read_attribute(f)
        val ? ("$" + val.to_f.with_commas) : nil
      end
      define_method("#{f}_humanized=") do |e|
        write_attribute(f,e.to_s.delete(",$"))
      end
    end
  end
end
于 2011-07-01T07:59:58.070 に答える
2

コンマ before_validation または before_save を削除してみることができます

おっと、変換される前にテキスト フィールドでそれを行いたいと思います。仮想属性を使用できます。

def price=(price)
   price = price.gsub(",", "")
   self[:price] = price  # or perhaps price.to_f
end
于 2011-06-30T21:32:53.810 に答える
0

日付と数値の解析とローカリゼーションについては、i18n_alchemy gem を参照してください。

I18nAlchemy は、現在の I18n ロケール形式に基づいて、日付、時刻、および数値の解析を処理することを目的としています。主なアイデアは、現時点では ActiveRecord などの ORM を使用して、現在のロケール形式で指定された日付/数値を自動的に受け入れ、これらの値もローカライズして返すことです。

于 2016-09-07T09:06:16.163 に答える
-1

数値入力が正しく読み取られることを確認する簡単な方法を次に示します。出力には、カンマではなくポイントが付きます。これは美しくありませんが、場合によっては少なくとも重要ではありません。

コンマ区切り文字を有効にするコントローラーで 1 つのメソッド呼び出しが必要です。MVCに関しては完璧ではないかもしれませんが、かなり単純です。例:

class ProductsController < ApplicationController

  def create
    # correct the comma separation:
    allow_comma(params[:product][:gross_price])

    @product = Product.new(params[:product])

    if @product.save
      redirect_to @product, :notice => 'Product was successfully created.'
    else
      render :action => "new"
    end
  end

end

アイデアは、パラメーター文字列を変更することです。たとえば、次のようになります。

class ApplicationController < ActionController::Base

  def allow_comma(number_string)
    number_string.sub!(".", "").sub!(",", ".")
  end

end
于 2012-03-20T10:49:45.477 に答える
-1

def price=(price)メソッドが自分自身を再帰的に呼び出しているように見えるため、以前の仮想属性の提案を実装できませんでした。

属性ハッシュからコンマを削除することになりました.ActiveRecordは、DECIMALフィールドに挿入されたコンマで入力を切り捨てていると思われるためです。

私のモデルでは:

before_validation :remove_comma

def remove_comma
  @attributes["current_balance"].gsub!(',', '')  # current_balance here corresponds to the text field input in the form view

  logger.debug "WAS COMMA REMOVED? ==> #{self.current_balance}"
end
于 2011-07-24T05:43:02.667 に答える