ActiveRecord — validation:allow_blank всегда активен, даже если у него есть: если

#ruby-on-rails #ruby-on-rails-3 #validation #activerecord

#ruby-on-rails #ruby-on-rails-3 #проверка #activerecord

Вопрос:

У меня есть эта модель

 class User < ActiveRecord::Base
  attr_accessible :type, :school_name, :school_grade

  validates :type, :inclusion =>{:in =>['1','2']}, :allow_blank => true
  validates :school_name,  :presence =>{:if => :student?}
  validates :school_grade, :numericality =>{:only_integer =>true}, :allow_blank => {:unless => :student?}

  def student?
    type.to_s == '1'
  end
end
  

Я попробовал следующие шаблоны.

 User.create(:type =>'2', :school_name =>nil, :school_grade =>nil)
  

=> OK. Ошибки не произошло.

 User.create(:type =>'1', :school_name =>nil, :school_grade =>1)
  

=> OK. Произошла ошибка ActiveRecord::RecordInvalid «имя_школы пусто».

 User.create(:type =>'1', :school_name =>'foo', :school_grade =>'string is not a number')
  

=> OK. Произошла ошибка проверки «school_grade не является числом».

 User.create(:type =>'1', :school_name =>'foo', :school_grade =>nil)
  

=> NG. Я ожидаю ошибку «school_grade — это не число», но ошибки не произошло.

Я тоже пробовал этот шаблон, но получил тот же результат.

   validates :school_grade, :numericality =>{:only_integer =>true}, :allow_blank => {:if => :not_student?}

  def not_student?
    type.to_s != '1'
  end
  

Я думаю, проверка: allow_blank всегда активна, но почему? И как это исправить?

Спасибо.

Комментарии:

1. какой тип данных type в БД?

Ответ №1:

allow_blank не принимает Hash , только логическое значение, поэтому вы не можете написать что-то подобное :allow_blank => {:unless => :student?} , как вы можете видеть в исходном activemodel-4.1.2/lib/active_model/validator.rb

 def validate(record)
  attributes.each do |attribute|
    value = record.read_attribute_for_validation(attribute)
    next if (value.nil? amp;amp; options[:allow_nil]) || (value.blank? amp;amp; options[:allow_blank])
    validate_each(record, attribute, value)
  end
end
  

Однако то, чего вы хотите достичь, может быть сделано в двух строках:

 class User < ActiveRecord::Base
  validates_presence_of :school_grade, :if => :student?
  validates :school_grade, :numericality =>{:only_integer =>true}, :allow_blank => true
end
  

Комментарии:

1. Этот код работает для меня. Но я получил validates_presence_of is deprecated in Rails , поэтому я изменил вот так. validates :school_grade, :presence =>true, :if => :student? Спасибо.

2. Хорошо. Но теперь мне любопытно и я беспокоюсь о причине моей настройки в Rails 4.1.2, я не получаю никаких предупреждений об амортизации. Я погуглил и обнаружил, что амортизация для validates_presence_of была в Rails 3. Какую версию вы используете?

3. Также в текущей версии git я не вижу никакого кода, связанного с амортизацией github.com/rails/rails/blob /…

4. Я использую Rails 3.2.18. Спасибо за вашу информацию. Это стало полезным.

Ответ №2:

Вы хотите, чтобы allow_blank был условным или чтобы проверка всей численности была полной?

Если последнее:

 validates :school_grade, :numericality =>{:only_integer =>true}, :allow_blank => true, :unless => :student?
validates :school_grade, :numericality =>{:only_integer =>true}, :allow_blank => false, :if => :student?
  

Комментарии:

1. Этот код допускает нецелочисленный параметр, когда student? есть false . Я хочу отклонить его, но только тогда, когда student? есть false , хочу разрешить nil . Спасибо.

2. Я обновил свой ответ. Выполните две проверки для school_grade. Один для случая student, один для случая not student.

3. Последний код работает хорошо. Но у Бенджамина проще, потому что в моем реальном коде есть другие проверки. В любом случае спасибо.