Подтвердить что ты не робот

Неисправность с accepts_nested_attributes_for при проверке внешнего ключа

Я использую Ruby on Rails v3.2.2. Я хотел бы решить проблему, связанную с проверкой внешнего ключа при использовании методов accepts_nested_attributes_for и validates_associated RoR. То есть, у меня есть следующие классы моделей:

class Article < ActiveRecord::Base
  has_many :category_associations, :foreign_key => 'category_id'

  accepts_nested_attributes_for :category_associations, :reject_if => lambda { |attributes| attributes[:category_id].blank? }
  validates_associated :category_associations
end

class CategoryAssociation < ActiveRecord::Base
  belongs_to :article, :foreign_key => 'article_id'
  belongs_to :category, :foreign_key => 'category_id'

  validates :article_id, :presence => true
  validates :category_id, :presence => true
end

... и у меня есть следующие действия с контроллером:

class ArticlesController < ApplicationController
  def new
    @article = Article.new
    5.times { @article.category_associations.build }

    # ...
  end

 def create
   @article = Article.new(params[:article])

   if @article.save
     # ...
   else
     # ...
   end
 end
end

С приведенным выше кодом ( "вдохновленный" "Часть вложенной модели" , часть 1 Rails Cast), я намерен хранить ассоциации категорий при создании статья (примечание: объекты категории уже присутствуют в базе данных, в моем случае я хотел бы просто создавать ассоциации создания классов). Однако, когда я передаю связанную форму из связанного файла вида, я получаю следующую ошибку (я регистрирую сообщения об ошибках):

{:"category_associations.article_id"=>["can't be blank"], :category_associations=>["is invalid"]}

Почему это происходит, поскольку validates_associated кажется для запуска метода article.category_association.valid?, но только если article.category_association.article_id не nil? Как я могу решить проблему с проверкой наличия внешнего ключа article_id?

Однако, если я прокомментирую validates :article_id, :presence => true в классе модели CategoryAssociation, он работает так, как ожидалось, но кажется, что это не правильный подход, чтобы не проверять внешние ключи.


Если я прокомментирую validates_associated :category_associations в классе модели Article, я все равно получаю ошибку:

{:"category_associations.article_id"=>["can't be blank"]}
4b9b3361

Ответ 1

Используйте inverse_of, чтобы связать ассоциации, а затем проверить наличие связанного объекта, а не наличие фактического внешнего ключа.

Пример документы:

class Member < ActiveRecord::Base
  has_many :posts, inverse_of: :member
  accepts_nested_attributes_for :posts
end

class Post < ActiveRecord::Base
  belongs_to :member, inverse_of: :posts
  validates_presence_of :member
end

Ответ 2

Поскольку у вас есть возможная вложенная форма с accepts_nested_attributes_for, поэтому в CategoryAssociation вам необходимо сделать проверку правильной, требуя наличия только для обновлений:

validates :article_id, presence: true, on: :update

Помимо ассоциаций Active Record, вы должны иметь ограничения внешнего ключа на уровне db.

Ответ 3

Проверки будут выполняться на create или save (как и следовало ожидать), поэтому спросите себя: "В каждом из них есть сохраненный экземпляр, на который ссылается?", потому что без сохранения экземпляр не будет иметь идентификатор, поскольку он является базой данных, которая присваивает идентификатор.


Изменить: Как я уже сказал в комментариях, если вы собираетесь спускать вниз, оставьте комментарий о том, почему.