AWDwR 有一个小节讲到了如何创建多对多映射,不过使用db:migrate使得这个过程变得更为简单,这是来自thembid.com 的一篇指南,原文在这里 。
为了让例子更容易理解一些,我修改了原文的两个表名,并使用了scaffold_resource替代了model,同时在最后给出了两个截图。这里我使用book和author来作为演示的resource,一本书可以有多个作者,一个作者也可能写了多本书,因此,作者和书属于多对多的关系。
首先,让我们创建resource:
ruby script/generate scaffold_resource book title:string
ruby script/generate scaffold_resource authors name:string
然后,我们为创建映射关系表:
ruby script/generate migration create_authors_books
编辑db/migrate/003_create_authors_books.rb:
class CreateAuthorsBooks < ActiveRecord::Migration
def self.up
create_table :authors_books, :id => false do |t|
t.column :author_id, :integer
t.column :book_id, :integer
end
add_index :authors_books, [:author_id, :book_id]
add_index :authors_books, [:book_id]
end
def self.down
remove_index :authors_books, [:book_id]
remove_index :authors_books, [:author_id, :book_id]
drop_table :authors_books
end
end
执行db:migrate,我们可以看到数据库中多了3个表:books, authors, books_authors。
修改app/models/book.rb:
class Book < ActiveRecord::Base
has_and_belongs_to_many :authors
end
修改app/models/author.rb:
class Author < ActiveRecord::Base
has_and_belongs_to_many :books
end
这就搞定了,不过为了照顾喜欢看截图的群众,这里还是准备了几张图:
修改app/views/books/index.rhtml:
<td><%=h book.title %> (
<% for author in book.authors %>
<%= author.name %>
<% end %>
)</td>
现在,books/index变成了这样,每本书的后面都有了作者信息(当然你首先需要在authors_books表中添加作者和书的映射关系):
如果愿意,你也可以修改authors/index.rhtml,在每个作者后面显示他的作品。

