Вы используете has_and_belongs_to_many
только тогда, когда вы устанавливаете связь «многие ко многим» (другими словами, когда на другой стороне также есть has_and_belongs_to_many
). В этом смысл этой ассоциации.
Вы должны иметь
class Tag < ActiveRecord::Base
has_many :posts_tags
has_many :posts, :through => :post_tags
end
class PostsTag < ActiveRecord::Base
belongs_to :tag
belongs_to :post
end
class Post < ActiveRecord::Base
has_many :posts_tags
has_many :tags, :through => :posts_tags
end
Обратите внимание, что я использовал множественное число, post_tags
(потому что это правильный путь).
Если у вас есть ситуация, как в вашем комментарии, вы должны иметь
belongs_to :post_tag
в вашей Post
модели и
has_many :posts
в вашей PostTag
модели.
Теперь вы можете спросить: «Почему я должен использовать belongs_to :post_tag
? Он не принадлежит тегу, он имеет тега. Поэтому я не должен использовать has_one :post_tag
?». Сначала это был и мой вопрос, но потом я понял, что Rails не всегда может идеально соответствовать английскому языку. Вам нужен столбец post_tag_id
на вашем post
, и belongs_to
ожидает именно этого. С другой стороны, has_one
будет ожидать, что столбец с именем post_id
присутствует на другой стороне , то есть на вашем post_tag
. Но это было бы невозможно, потому что post_tag
имеет много posts
(не только один), поэтому идентификаторы post
нельзя хранить в post_tags
.
Обновление
Разница между ассоциациями заключается только в предоставляемых вами методах и опциях, которые вы можете передать (объяснено в руководстве Rails по ассоциациям). Например, has_one
и belongs_to
имеют одинаковые методы:
association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
Но, например, методы association=
и create_association
подразумевают разные вещи относительно того, где должен находиться внешний ключ (как я объяснил выше).
has_and_belongs_to_many
и has_many
, вероятно, не имеют ничего отличного в своих методах, но они отличаются в вариантах, которые вы можете передать. Например, вы можете передать в
:dependent => :destroy
в ассоциации has_many
, но вы не можете передать ее в has_and_belongs_to_many
, потому что это не имеет смысла, поскольку подразумевает связь многих со многими; если родительская запись уничтожена, дочерние записи все равно могут быть связаны с другими записями, поэтому их также не следует уничтожать.