Rails 3 - Пользовательский валидатор - PullRequest
0 голосов
/ 08 марта 2012

Я пытаюсь настроить собственный валидатор в моем приложении.

Я уже настроил config.autoload.paths, и он нормально загружается.

Проблема с самим валидатором.

Результат binding pry

instance variables: @attributes  @options  @with
locals: _  _dir_  _ex_  _file_  _in_  _out_  _pry_  attribute  record  value
[12] pry(#<FileCountValidator>)> value
=> [#<Attachment id: 60, description: nil, file: "cache_600_1__img_948867_5770137d84a6c79ac825886938e...", attachable_type: "Post", attachable_id: 15, created_at: "2012-03-10 14:50:54", updated_at: "2012-03-10 14:50:54">,
 #<Attachment id: 61, description: nil, file: "cache_600_1__img_948867_90f64e01b9c871ec656a884e015...", attachable_type: "Post", attachable_id: 15, created_at: "2012-03-10 14:50:54", updated_at: "2012-03-10 14:50:54">,
 #<Attachment id: 62, description: nil, file: "cache_600_1__img_948867_85eda3946c27fa90566403ac941...", attachable_type: "Post", attachable_id: 15, created_at: "2012-03-10 14:50:54", updated_at: "2012-03-10 14:50:54">,
 #<Attachment id: nil, description: nil, file: nil, attachable_type: "Post", attachable_id: 15, created_at: nil, updated_at: nil>]
[13] pry(#<FileCountValidator>)> value > @with
TypeError: compared with non class/module
from /home/kleber/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.1/lib/active_record/relation/delegation.rb:20:in `>'
[14] pry(#<FileCountValidator>)> value.size > @with
=> true
[15] pry(#<FileCountValidator>)> value.size
=> 4
[16] pry(#<FileCountValidator>)> @with
=> 3
[17] pry(#<FileCountValidator>)> 

Итак, я пытаюсь сделать это сравнение таким же, как я делал на консоли отладки pry.

def validate_each(record, attribute, value)
  #binding.pry
   record.errors.add(attribute,"#{@with} attachments per post only. #{attribute['file'].size} detected.") if value.size > @with
  end

Но, сделав это, верните мне ошибку:

NoMethodError (undefined method `size' for nil:NilClass):
  lib/validators/file_count_validator.rb:11:in `validate_each'
  app/controllers/posts_controller.rb:61:in `block in update'
  app/controllers/posts_controller.rb:60:in `update'

Есть ли способ поймать value, прежде чем он войдет в метод validate_each?

1 Ответ

2 голосов
/ 09 марта 2012

Извините, но передаваемое значение кажется правильным. value подразумевается как значение этого атрибута для этой записи, т. Е. record.send(attribute) должно быть равно значению.

Вызов validates :attachments, :photo_count => 2 не отправляет 2 методу validate_each в качестве аргумента value. Вы можете сделать :photo_count => true, что я обычно делаю, или даже :photo_count => "foo". photo_count в вашем операторе validates служит для обеспечения того, чтобы валидатор вызывался путем передачи значения (т. Е. 2 ​​или true или "foo" для указанных примеров), встроенного в хэш параметров.

Вот способ без передачи ограничения валидатору .

Создайте класс Constants и определите MAX_ATTACHMENTS константу. У меня обычно это есть в models / constants.rb.

class Constants
  MAX_ATTACHMENTS = 1
end

Тогда в валидаторе вы можете сделать

class PhotoCountValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add(attribute,"#{Constants::MAX_ATTACHMENTS} attachments per post only.") if record.send(attribute).size > Constants::MAX_ATTACHMENTS
  end
end

Другой способ передачи параметра в валидатор :

validates :attachments, :photo_count => 3 #desired_limit

Переопределить метод initialize для класса PhotoCountValidator и инициализировать переменную класса:

def initialize(options)
  @@max_objects = options[:with] # the options hash will be as {:attributes=>[:attachments], :with=>3}, where :with contains the desired limit passed
  super
end

Тогда в методе validate_each:

record.errors.add(attribute,"#{@@max_objects} attachments per post only.") if record.send(attribute).size > @@max_objects
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...