#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.