我要活下去!!!

以前不敢問問題,到現在看到什麼就想問,根本忘了先_查資料_,再發問。

問問題前,應該先查資料,再把不了解的濃縮成人話(當然這很難!!!

難的地方不是發問,而是要很讓人聽懂。

以下是得到的解答,透過我的大腦,解析出的人話(?
或許不對,不清楚,再麻煩大家包涵或者直接幹瞧我喔^_<

單一表格繼承STI(Single-table inheritance)

如何將物件導向中的繼承概念,對應到關聯式資料庫的設計,是個大哉問。Rails內建了其中最簡單的一個解法,只用一個資料表儲存繼承體系中的物件,搭配一個type欄位用來指名這筆資料的類別名稱。要開啟STI功能,依照慣例只要有一個欄位叫做type,型態字串即可

比方說:我有一個 Animal Model,為了要有繼承功能,我們新增 type這個欄位。

1
2
3
4
5
6
7
def change
  create_table :animals do |t|
    t.string :name
    t.string :type
    t.timestamps null: false
  end
end

那要被繼承的 Dog、Cat兩個 Model就不用在建立表格欄位了。

1
2
3
4
5
6
7
8
class Animal < ActiveRecord::Base
end

class Dog < Animal
end

class Cat < Animal
end

這時候他們都繼承了Animal這個爸爸,爸爸有什麼,他們就有什麼了。
但缺點就是,爸爸有的,你不一定需要,但你還是得擁有那些欄位。
如果要關閉的話就在爸爸身上加上 self.abstract_class = true

多型關聯(Polymorphic Associations)

多型關連(Polymorphic Associations)可以讓一個 Model 不一定關連到某一個特定的 Model,秘訣在於除了整數的_id外部鍵之外,再加一個字串的_type欄位說明是哪一種Model。

多型關聯,當你有某種事情需求,已經有Model在做那件事情時。
我在其他Model,也想使用到那件事情時,我就不用在另外建立Model,來做一樣的事情了。

以上想用自己的話表達簡單一點,但覺得太攏統,太模糊了

以下引用文件

例如一個Comment model,我們可以透過多型關連讓它belongs_to到各種不同的 Model上,假設我們已經有了Article與Photo這兩個Model,然後我們希望這兩個Model都可以被留言。不用多型關連的話,你得分別建立ArticleComment和PhotoComment的model。用多型關連的話,無論有多少種需要被留言的Model,只需要一個Comment model即可:

rails g model comment content:text commentable_id:integer commentable_type

產生出

1
2
3
4
5
6
7
8
9
10
11
class CreateComments < ActiveRecord::Migration[5.1]
  def change
    create_table :comments do |t|
      t.text :content
      t.integer :commentable_id
      t.string :commentable_type

      t.timestamps
    end
  end
end

這個Migration檔案中,我們用content這個欄位來儲存留言的內容,commentable_id用來儲存被留言的物件的id而commentable_type則用來儲存被留言物件的種類,以這個例子來說被留言的對象就是Article與Photo這兩種Model,這個Migration檔案也可以改寫成下面這樣:

1
2
3
4
5
6
7
8
9
10
11
class CreateComments < ActiveRecord::Migration[5.1]
  def change
    create_table :comments do |t|
      t.text :content
      t.belongs_to :commentable, :polymorphic => true
      #同時會幫你產生出[:commentable_id, :commentable_type]

      t.timestamps
    end
  end
end

這時就必須指定關聯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Comment < ApplicationRecord
  belongs_to :commentable, :polymorphic => true
                          #透過true來將此關聯指定是多型關聯
end

class Article < ApplicationRecord
  has_many :comments, :as => :commentable
                      #我們用:as來指定 :commentable這個參數作為多型關聯的接口
                      #:as是什麼?可以看has_one or has_many API
end

class Photo < ApplicationRecord
  has_many :comments, :as => :commentable
end

接下來可以透過關聯來新增留言

1
2
3
4
5
6
7
8
9
10
11
article = Article.first

#透過關連新增留言
comment = article.comments.create(:content => "First Comment")

#你可以發現 Rails 很聰明的幫我們指定了被留言物件的種類和id
comment.commentable_type => "Article"
comment.commentable_id => 1

#也可以透過 commentable 反向回查關連的物件
comment.commentable => #<Article id: 1, ....>

簡單來說,我有一個留言的model了,我在文章與照片都想要可以留言,既然已經有model在做這件事了,
我們就使用多型關聯來連到那裡去。就不用說還需要再另外建立什麼了。

文章引用參考至:
https://ihower.tw/rails/activerecord-relationships.html
https://ihower.tw/rails/activerecord-others.html

-W