has_and_belongs_to_many与流派和书籍的关联

时间:2016-01-25 04:43:57

标签: ruby-on-rails

我有两本模特的书和类型。我想列出一本书可能具有的所有类型。例如幻想,浪漫等。每本书都有很多类型,我希望在创建它时将每种类型添加到该特定书中。 has_and_belongs_to_many协会会更好吗?

我已经完成了下面的工作并且它有效但我必须在创建一本书和类型后单独添加每本书和类型。

 class Book < ActiveRecord::Base
  has_many :book_genre_relations
  has_many :genres, through: :book_genre_relations


 class Genre < ActiveRecord::Base
  has_many :book_genre_relations
  has_many :books, through: :book_genre_relations


 class BookGenreRelation < ActiveRecord::Base
  belongs_to :book
  belongs_to :genre

2 个答案:

答案 0 :(得分:1)

你的代码是正确的(尽管我会从该模型中删除关系一词,但并不是真的需要)。

你说: “......但我必须在创作一本书和类型之后单独添加每本书和类型。”

但我认为你的意思是: “......但是我必须在创建一本书和类型之后在关系表中添加一本书/类型记录。”

所以如果你的意思是你在做这样的事情:

my_book = Book.create(<attributes>)
my_genre = Genre.create(<attributes>)
BookGenreRelation.create(book: my_book, genre: my_genre)

那么你也是正确的,就是如何在两个对象之间建立链接。

如果您有其他意思,请发布您用来创建对象的代码。

要回答关于使用'has_and_belongs_to_many'的问题,我的建议是否定的。你现在的方式是非常标准的Rails方法。

如果你想知道为什么我的建议不是,read this

答案 1 :(得分:1)

您将受益于this article (choosing between has_many :through and has_and_belongs_to_many)

  

最简单的经验法则是,如果您需要将关系模型作为独立实体使用,则应设置has_many :through关系

从发展的角度来看,HMT和{}之间没有太大区别。 HABTM。您可以使用两个实例中的以下内容实现您想要的效果:

@book   = Book.find params[:id]
@genres = @book.genres

最大的区别在于您是否希望存储额外的&#34;加入&#34;您的联接模型中的数据(EG&#34;字幕&#34;图像等)。

只有使用has_many :through才能节省额外费用&#34;加入&#34;数据。 HMT基本上是&#34;哑巴&#34;从某种意义上说,您可以向关联添加对象,但它们只是数据库引用。

-

就我个人而言,我会使用has_and_belongs_to_many - 您对genres的额外属性/方法没有特殊需求,因此只想将两者联系起来:

#app/models/book.rb
class Book < ActiveRecord::Base
   has_and_belongs_to_many :genres
end

#app/models/genre.rb
class Genre < ActiveRecord::Base
   has_and_belongs_to_many :books
end

以上使您能够使用<<&amp;您可以使用.delete方法,如下所示:

@book  = Book.find params[:id]
@genre = Genre.find_by name: "Horror"

@book.genres << @genre     if @genre #-> adds to association
@book.genres.delete @genre if @genre #-> removes from association

-

您还需要识别架构中的区别:

has_and_belongs_to_manyenter image description here

has_many :throughenter image description here

HABTM在表格中没有primary_key或任何其他属性。这意味着它只能充当join table