Обработка международной валюты вводится в Ruby on Rails

Мне 19 лет, запущенных использовать emacs в прошлом году, и мне нравится он. Даже при том, что я не знаю, как использовать его "усовершенствованные" функции все же, я доволен тем, что они существуют, и я мог изучить их при необходимости.

В моем колледже, не должно быть намного больше чем 5 студентов, использующих Emacs или Vi, все же.

9
задан Tim Sullivan 3 November 2009 в 18:22
поделиться

4 ответа

Вы можете дать этому снимок:

   def string_to_float(string)

      string.gsub!(/[^\d.,]/,'')          # Replace all Currency Symbols, Letters and -- from the string

      if string =~ /^.*[\.,]\d{1}$/       # If string ends in a single digit (e.g. ,2)
        string = string + "0"             # make it ,20 in order for the result to be in "cents"
      end

      unless string =~ /^.*[\.,]\d{2}$/   # If does not end in ,00 / .00 then
        string = string + "00"            # add trailing 00 to turn it into cents
      end

      string.gsub!(/[\.,]/,'')            # Replace all (.) and (,) so the string result becomes in "cents"  
      string.to_f / 100                   # Let to_float do the rest
   end

и тестовые случаи:

describe Currency do
  it "should mix and match" do
    Currency.string_to_float("$ 1,000.50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,--").should eql(1000.to_f)
    Currency.string_to_float("$ 1,000.--").should eql(1000.to_f)    
  end     

  it "should strip the € sign" do
    Currency.string_to_float("€1").should eql(1.to_f)
  end

  it "should strip the $ sign" do
    Currency.string_to_float("$1").should eql(1.to_f)
  end

  it "should strip letter characters" do
    Currency.string_to_float("a123bc2").should eql(1232.to_f)
  end

  it "should strip - and --" do
    Currency.string_to_float("100,-").should eql(100.to_f)
    Currency.string_to_float("100,--").should eql(100.to_f)
  end

  it "should convert the , as delimitor to a ." do
    Currency.string_to_float("100,10").should eql(100.10)
  end

  it "should convert ignore , and . as separators" do
    Currency.string_to_float("1.000,10").should eql(1000.10)
    Currency.string_to_float("1,000.10").should eql(1000.10)
  end

  it "should be generous if you make a type in the last '0' digit" do
    Currency.string_to_float("123,2").should eql(123.2)
  end
11
ответ дан 4 December 2019 в 08:52
поделиться

Вам необходимо очистить ввод, чтобы пользователи могли вводить практически все, что захотят, и вы получите что-то согласованное для хранения в вашей базе данных. Предположим, ваша модель называется «DoughEntry», а ваш атрибут - «amount» и хранится как целое число.

Вот метод, который преобразует введенную строку в центы (если строка заканчивается двумя цифрами после разделителя, предполагается, что это центы). Возможно, вы захотите сделать это умнее, но вот концепция:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567

Затем перезапишите средство доступа по умолчанию "amount", передав его через этот метод:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

Теперь вы храните центы в базе данных. У радара есть правильная идея вытащить его обратно.

Я получу что-то согласованное для хранения в вашей базе данных. Предположим, ваша модель называется «DoughEntry», а ваш атрибут - «amount» и хранится как целое число.

Вот метод, который преобразует введенную строку в центы (если строка заканчивается двумя цифрами после разделителя, предполагается, что это центы). Возможно, вы захотите сделать это умнее, но вот концепция:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567

Затем перезапишите метод доступа по умолчанию "amount", передав его через этот метод:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

Теперь вы сохраняете центы в базе данных. У радара есть правильная идея вытащить его обратно.

Я получу что-то согласованное для хранения в вашей базе данных. Предположим, ваша модель называется «DoughEntry», а ваш атрибут - «amount» и хранится как целое число.

Вот метод, который преобразует введенную строку в центы (если строка заканчивается двумя цифрами после разделителя, предполагается, что это центы). Возможно, вы захотите сделать это умнее, но вот концепция:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567

Затем перезапишите средство доступа по умолчанию "amount", передав его через этот метод:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

Теперь вы храните центы в базе данных. У радара есть правильная идея вытащить его обратно.

sa, который преобразует введенную строку в центы (если строка заканчивается двумя цифрами после разделителя, предполагается, что это центы). Возможно, вы захотите сделать это умнее, но вот концепция:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567

Затем перезапишите метод доступа по умолчанию "amount", передав его через этот метод:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

Теперь вы сохраняете центы в базе данных. У радара есть правильная идея вытащить его обратно.

sa, который преобразует введенную строку в центы (если строка заканчивается двумя цифрами после разделителя, предполагается, что это центы). Возможно, вы захотите сделать это умнее, но вот концепция:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567

Затем перезапишите средство доступа по умолчанию "amount", передав его через этот метод:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

Теперь вы храните центы в базе данных. У радара есть правильная идея вытащить его обратно.

4
ответ дан 4 December 2019 в 08:52
поделиться

Тим,

Вы можете попробовать использовать функцию «агрегирования» в сочетании с классом делегирования. Я бы сделал что-то вроде:

class Product
  composed_of :balance, 
         :class_name => "Money", 
         :mapping => %w(amount)
end

class Money < SimpleDelegator.new
   include Comparable
   attr_reader :amount

   def initialize(amount)
     @amount = Money.special_transform(amount)
     super(@amount)
   end

   def self.special_transform(amount)
     # your special convesion function here
   end

   def to_s
     nummber_to_currency @amount
   end
 end

Таким образом, вы сможете напрямую назначить:

Product.update_attributes(:price => '12.244,6')

или

Product.update_attributes(:price => '12,244.6')

Преимущество в том, что вам не нужно изменять что-либо на контроллерах / представлениях.

2
ответ дан 4 December 2019 в 08:52
поделиться

Использование преобразования для чисел во встроенном I18n должно позволить вам вводить цены в одном формате (1234.56), а затем с помощью I18n выводить их обратно с помощью number_to_currency , чтобы они автоматически распечатывались с правильной локалью.

Конечно, вам придется установить I18n.locale с помощью before_filter , проверьте Руководство I18n , раздел 2.3.

2
ответ дан 4 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: