Лучше метод validates_associated для Rails 3? - PullRequest
18 голосов
/ 08 сентября 2010

Rails 3 включает validates_associated, который автоматически вызывается при сохранении вложенной модели.Проблема метода заключается в том, что сообщение ужасно - «Недопустимые модели»

Было несколько сообщений, посвященных этой проблеме для Rails 2:

и, возможно, есть и другие.Было бы здорово иметь лучшую версию, как описано в этих постах, совместимую с Rails 3.Основным улучшением будет включение , почему связанная модель не работает.

Ответы [ 4 ]

5 голосов
/ 14 февраля 2012

В отношении вы можете вместо этого использовать :autosave => true, который будет пытаться сохранить дочерние модели при сохранении родительского. Это автоматически запустит проверки дочерних элементов и они сообщат с соответствующими сообщениями об ошибках.

Более того, если вы добавляете проверку присутствия на дочернем объекте, что родительский объект должен быть установлен, и вы создаете дочерние объекты посредством ассоциации, вам даже не нужен флаг autosave, и вы получаете красивое сообщение об ошибке. , Например:

class Trip < ActiveRecord::Base
  validates :name, :presence => true

  attr_accessible :name

  has_many :places, dependent: :destroy, :inverse_of => :trip
end

class Place < ActiveRecord::Base
  belongs_to :trip

  validates :name, :trip, presence: true

  attr_accessible :name
end

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

> trip = Trip.new(name: "California")
=> #<Trip id: nil, name: "California"> 
> trip.places.build
=> #<Place id: nil, name: nil, trip_id: nil>
> trip.valid?
=> false
> trip.errors
=> #<ActiveModel::Errors:0x00000004d36518 @base=#<Trip id: nil, name: "California">, @messages={:places=>["is invalid"]}>
> trip.errors[:places]
=> ["is invalid"] 

Я думаю, validates_associated - пережиток эпохи до автосохранения детей и больше не лучший способ что-либо сделать. Конечно, это не обязательно хорошо документировано. Я не уверен на 100%, что это относится и к Rails 2.3, но у меня такое чувство. Эти изменения произошли, когда была добавлена ​​функция вложенных атрибутов (что было когда-то в 2.x).

Это упрощенный фрагмент кода из учебного проекта , который я разместил на github .

3 голосов
/ 28 ноября 2012

У меня была эта проблема, и в конце концов я использовал решение, заданное здесь Бен Ли :

, связанное с сообщением об ошибке модели

Бен говорит:

Вы можете написать свой собственный валидатор на основе кода для встроенного валидатора.

Поиск исходного кода для validates_associated, мы видим, что он использует«AssociatedValidator».Исходный код для этого:

module ActiveRecord
  module Validations
    class AssociatedValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        return if (value.is_a?(Array) ? value : [value]).collect{ |r| r.nil? || r.valid? }.all?
        record.errors.add(attribute, :invalid, options.merge(:value => value))
      end
    end

    module ClassMethods
      def validates_associated(*attr_names)
        validates_with AssociatedValidator, _merge_attributes(attr_names)
      end
    end
  end
end

Таким образом, вы можете использовать это в качестве примера для создания собственного валидатора, который выдает сообщения об ошибках, подобные этому:

module ActiveRecord
  module Validations
    class AssociatedBubblingValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        (value.is_a?(Array) ? value : [value]).each do |v|
          unless v.valid?
            v.errors.full_messages.each do |msg|
              record.errors.add(attribute, msg, options.merge(:value => value))
            end
          end
        end
      end
    end

    module ClassMethods
      def validates_associated_bubbling(*attr_names)
        validates_with AssociatedBubblingValidator, _merge_attributes(attr_names)
      end
    end
  end
end

Вы можете поместить этот кодв инициализаторе что-то вроде /initializers/associated_bubbling_validator.rb.

Наконец, вы должны выполнить проверку так:

class User < ActiveRecord::Base
 validates_associated_bubbling :account
end

ПРИМЕЧАНИЕ: приведенный выше код полностью не проверен, но если это не такне работает, надеюсь, достаточно поставить вас на правильный путь

1 голос
/ 03 марта 2011

validates_associated запускает проверки, указанные в классе связанного объекта. Ошибки на уровне родительского класса просто говорят «мой ребенок недопустим». Если вам нужны подробности, выставьте ошибки на дочернем объекте (на уровне дочерней формы в представлении).

0 голосов
/ 26 января 2011

Большую часть времени validates_existence_of - это все, что мне нужно.

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