over 4 years ago

本章將淺談:
從本 blog 裡用到的 Database Relationship (資料庫關聯) 為例
解說 Rails 裡的 Active Record Association

  • 基本概念
  • 延伸運用
  • 多對多關聯

基本概念

我們在 3 - 0. 可以在討論版裡發表文章 ( 前置設定 ) 裡有做到

app/models/group.rb
class Group < ActiveRecord::Base
  has_many :posts
end
app/models/post.rb
class Post < ActiveRecord::Base
    belongs_to :group
end

來把 group 跟 post 這二個資料建立關聯

二者之間的關係圖如下:

在 Rails 的架構裡面,只要『 被屬於 』(本例是 post ) 的資料表有 『 擁有者_id 』(本例是 group_id ) 的欄位
即可成為二資料表間關聯性的『 索引 』

舉例來說

假設 post 的資料表內容如下

當我們在 controller or rails console 模式輸入

group.find(1).posts.all

意思等於 => 列出 id 是 1 的 group 裡所擁有的全部 posts => 找出 group_id 是 1 的 posts

就像這樣

這時候再回頭看 groups_controller.rb 裡的 show action

app/controllers/groups_controller.rb
  def show
    @group = Group.find(params[:id])
    @posts = @group.posts
  end

以上就是 Active Record Association 的基本概念


延伸運用

我們在 4 - 2. 使用者功能帶進 group 與 post 裡 ( 作者機制 ) 有做:

app/models/user.rb
class User < ActiveRecord::Base

    has_many :groups
    has_many :posts
  
end
app/models/group.rb
class Group < ActiveRecord::Base

  belongs_to :owner, :class_name => "User", :foreign_key => :user_id
  
  def editable_by?(user)
    user && user == owner
  end
end
app/models/post.rb
class Post < ActiveRecord::Base
...
...
  belongs_to :author, :class_name => "User", :foreign_key => :user_id

  def editable_by?(user)
    user && user == author
  end
end

在本例裡面,其實 group 跟 post 都是 belongs_to :user
我們可以去客製化,讓

User.find(params[:id]).groups => User.find(params[:id]).owners
User.find(params[:id]).posts  => User.find(params[:id]).authors

Group.find(params[:id]).user  => Group.find(params[:id]).owner  # group 的擁有者 id

Post.find(params[:id]).user   => Post.find(params[:id]).author # post 的作者 id

只要先設定好自定的變數,然後定義好對應的資料表 ( :class_name => "User" ),
以及 『 索引 』 ( :foreign_key => :user_id ) 即可


多對多關聯

我們在 5 - 0. user 可以加入、退出 group 裡面做出
users 跟 groups 的多對多關聯

它的原理概念是這樣:

藉由一個中介資料表 ( group_user ) 來做到多對多關聯

app/models/user.rb
  has_many :group_users
  has_many :participated_groups, :through => :group_users, :source => :group
end
app/models/group_user.rb
class GroupUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end
app/models/group.rb
class Group < ActiveRecord::Base
 
  has_many :group_users
  has_many :members, :through => :group_users, :source => :user

其中

has_many :members,             :through => :group_users, :source => :user
has_many :participated_groups, :through => :group_users, :source => :group

代表此變數 ( memebers, participated_groups ) 是經由 ( through ) group_users 這個資料表
來取得 ( user , group ) 資料

範例

如果

User.find(1).participated_groups.all <=== 我們的使用者後台列出 使用者所加入的 group 就是用這原理做成的

等同於

如果

Group.find(1).members.all <=== 可以用此概念來列出該 group 所有成員

等同於


← [延伸閱讀] Strong Parameters [ 2.0 ] 1. 創建一個 Rails 專案 →
 
comments powered by Disqus