Как получить доступ к связанным атрибутам таблицы при проверке, прежде чем они будут сохранены в Ruby on Rails

#ruby-on-rails #validation #nested-attributes

#ruby-on-rails #проверка #вложенные атрибуты

Вопрос:

Я хочу иметь возможность пропустить проверку, если для определенного атрибута установлено значение false, скажем, status, проблема в том, что эта модель имеет много вложенных атрибутов к ним, и им также нужно пропустить проверку, если status равно false.

Цель такого внедрения заключается в том, что если кто-то захочет сохранить черновик записи в форме, по какой-либо причине ее прохождение через проверку может остановить их сохранение, что нежелательно, и требуется только проверять записи, которые становятся общедоступными, устанавливая статус true.

Пример ниже

статус атрибута, расположенный в статье

 model Article
  has_many :sub_articles
  accepts_nested_attributes_for :sub_articles, :allow_destroy => true

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

model SubArticle
  belongs_to :article
  has_many :foos
  accepts_nested_attributes_for :foos, :allow_destroy => true    

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.status }

model Foo
  belongs_to :sub_article

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article.article.status }
  

пропуск проверки для Article будет работать, но не для SubArticle или Foo, поскольку они не были сохранены, и идентификаторы там не установлены, что не позволяет им просматривать ассоциации, как в примере.

Возможно ли получить доступ к связанным атрибутам таблицы в момент проверки?

Любая помощь была бы высоко оценена.

——Обновлено——

Причина, по которой проверка для SubArticle и Foo завершается неудачей, заключается в

неопределенный метод `status’ для nil:NilClass

Это ожидается из-за того, что во время проверки article_id или sub_article_id по-прежнему равны нулю, я подтвердил это, выполнив

 model SubArticle
  belongs_to :article
  has_many :foos

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.check_attributes }

def check_attributes
  pp self
end
  

ведьма выдает

 #<SubArticle id: nil, body: "", article_id: nil, created_at: nil, updated_at: nil >
  

——обновлено 2———-

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

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

1. Не могли бы вы опубликовать краткий пример того, как вы планируете использовать модели?

Ответ №1:

Это возможно, но вам нужно использовать => вместо = . Вот так:

 validate_presence_of :body, :unless => Proc.new{|article| !article.status }
  

Пожалуйста, посмотрите:http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation для получения дополнительной информации об условных проверках.

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

1. извините за те, где были опечатки, исправил их. Это отлично работает с моделью Article, но не с SubArticle или Foo.

2. это действительно странно, у меня это работает идеально. Какую версию rails вы используете?

3. используя Rails 3.0.7 с ruby 1.8.7, обновленный вопрос, код будет работать при обновлении, но не будет выполнен при создании.

Ответ №2:

Как насчет условной проверки идентификатора?

 model Article
  has_many :sub_articles

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

    model SubArticle
      belongs_to :article
      has_many :foos

      validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article_id}

model Foo
  belongs_to :sub_article

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article_id }
  

Не уверен, сработает ли это, но вы, по сути, запускаете проверку только в том случае, если родительская модель сохранена и, следовательно, имеет идентификатор. Однако для обновлений это не сработает. Возможно, для обновления подойдет сочетание этого и вашего исходного кода?

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

1. Но не будет ли это означать, что проверка будет пропущена независимо от атрибута status при создании? Возможно, что статус true при создании.

Ответ №3:

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

 model Article
  has_many :sub_articles, :inverse_of => :article

  validate_presence_of :body, :unless => Proc.new{|article| !article.status }

model SubArticle
  belongs_to :article, :inverse_of => :sub_articles
  has_many :foos, :inverse_of => :foo

  validate_presence_of :body, :unless => Proc.new{|sub_article| !sub_article.article.status }

model Foo
  belongs_to :sub_article, :inverse_of => :foos

  validate_presence_of :body, :unless => Proc.new{|foo| !foo.sub_article.article.status }
  

Это позволит экземпляру, проверяемому на всех уровнях, иметь доступ к атрибуту status.