今天被問了一個問題當場答不出來,記錄起來,回家後試著實作看看

建立滿足以下關係的Table Associations

  1. User can create a tag for a book.
  2. According to a given tag, return book list.
  3. According to a given book, return tag list.

提示:需要用到2個Join Table

以下作法不確定是否正確,閱讀時請斟酌

需要建立5個Table

Users
1
2
3
4
5
6
7
8
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamp
end
end
end
Books
1
2
3
4
5
6
7
8
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.string :title
t.timestamps
end
end
end
Tags
1
2
3
4
5
6
7
8
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.text :label
t.timestamps
end
end
end
UserTags
1
2
3
4
5
6
7
8
class CreateUserTags < ActiveRecord::Migration
def change
create_table :user_tags do |t|
t.integer :user_id
t.integer :tag_id
end
end
end
BookTags
1
2
3
4
5
6
7
8
class CreateBookTags < ActiveRecord::Migration
def change
create_table :book_tags do |t|
t.integer :book_id
t.integer :tag_id
end
end
end

接著是Model設定

User
1
2
3
4
class User < ActiveRecord::Base
has_many :user_tags
has_many :tags, through: :user_tags
end
Book
1
2
3
4
class Book < ActiveRecord::Base
has_many :book_tags
has_many :tags, through: :book_tags
end
Tag
1
2
3
4
5
6
7
class Tag < ActiveRecord::Base
has_many :user_tags
has_many :users, through: :user_tags

has_many :book_tags
has_many :books, through: :book_tags
end
UserTag
1
2
3
4
class UserTag < ActiveRecord::Base
belongs_to :user
belongs_to :tag
end
BookTag
1
2
3
4
class BookTag < ActiveRecord::Base
belongs_to :book
belongs_to :tag
end

然後在Rails Console下測試

1
2
3
4
5
6
7
8
9
10
11
12
# Create data
> User.create(name: "Tomo")
> Book.create(title: "Ruby")
> Tag.create(label: "good book")
> User.first.tags << Tag.first
> Book.first.tags << Tag.first

# Test associations
> User.first.tags # return tags belong to user
> Book.first.tags # return tags belong to book
> Tag.first.users # return tag's users
> Tag.first.books # return tag's books

看起來都有正常連結,這個作法的缺點應該是在user_tags和book_tags都有記錄tag_id這個橍位,在空間上的利用效率較差。不過目前我也沒想到其它的方法就是了。