Ruby Regex для цены - PullRequest
       1

Ruby Regex для цены

2 голосов
/ 14 ноября 2011

Этот сбой, когда ноль в конце

12.12 проходов 5,51 проходов 12.50 не удается 12.60 не удается

 price_regex = /^\d+(\.\d{2})?$/

почему? и как мне это исправить?

Дополнительная информация

в _form.html.erb

  <p>
    <%= f.label :price %><br />
    <%= f.text_field :price %>
  </p>

в menu_item.rb

  price_regex = /^\d+(\.\d{2})?$/
  validates :price, :presence => true,
                :format => {  :with => price_regex  }

в menu_items_controller.rb

  def create
    @menu_item = MenuItem.new(params[:menu_item])

    if @menu_item.save
     respond_with @menu_item, :location => menu_items_url
   else
     flash[:notice] = "Not Saved"
       end
   end

цена является десятичной в базе данных с точностью до 2.

Ответы [ 3 ]

3 голосов
/ 14 ноября 2011

Вы говорите, что price - это "десятичное число в базе данных с точностью до 2". Это означает, что price представляется как BigDecimal в Ruby, и тест регулярного выражения будет выполняться в строковой форме этого BigDecimal. Немного экспериментов прояснит ситуацию:

> p = BigDecimal.new('12.50')
 => #<BigDecimal:12a579e98,'0.125E2',18(18)> 
> p.to_s
 => "12.5" 

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

/^\d+(\.\d{1,2})?$/
1 голос
/ 29 апреля 2014

Я использую Rails 3 с гемом client_side_validations, что означает, что мне нужен Regexp, который работает как в Ruby, так и в Javascript.У меня также есть четкое разграничение между внешним интерфейсом и внутренним форматом - пользователь никогда не должен иметь возможность вводить «$ 12,5», но как только он попадет на сервер, меня не волнует конечный 0. 0. 1001 *

Мое решениеЯ должен был добавить расширение ядра (в моем случае, для Float, но BigDecimal, вероятно, было бы более подходящим в большинстве случаев):

class Float
  def can_convert_to_i_with_no_loss_of_precision
    (self % 1).zero?
  end
  alias_method :to_s_with_loss_of_trailing_zeroes, :to_s
  def to_s
    if can_convert_to_i_with_no_loss_of_precision
      to_i.to_s
    else
      "#{to_s_with_loss_of_trailing_zeroes}#{0 if (self * 10 % 1).zero?}"
    end
  end
end

Теперь я могу использовать это в модели, и он хорошо играет навнешний интерфейс (Javascript не преобразует его в число с плавающей точкой, поэтому пользователь всегда будет вынужден вводить 2 цифры после десятичной дроби) и на внутренней стороне (где FormatValidator в ActiveModel будет вызывать to_s, а расширение ядра будет знать, когда добавитьконечный 0):

validates :price, :format => { :with => /^\d+(\.\d{2})?$/, :allow_blank => true }
0 голосов
/ 14 ноября 2011

регулярное выражение выглядит хорошо для меня.Я протестировал его на Rubular с указанными вами входными данными и несколькими другими, и он правильно фиксирует их все.

Проблема, скорее всего, связана с какой-то другой частью кода.Возможно, вы используете price = <regex>, тогда как вы должны использовать price =~ <regex> для сопоставления строки с регулярным выражением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...