其實 index: true
跟 foreign_key: true
的用意不同,我用一個 migration,把幾種排列組合都列出來:
class CreateStores < ActiveRecord::Migration[5.1]
def change
create_table :stores do |t|
t.string :title
t.string :address
# 純用 integer
t.integer :user_int_id
# 用 integer 並且加上 index
t.integer :user_int_index_id, index: true
# 用 integer 並且加上 foreign_key
t.integer :user_int_key_id, foreign_key: true
# 純用 references
t.references :user_ref
# 用 references 並且加上 index
t.references :user_ref_index, index: true
# 用 references 並且加上 foreign_key
t.references :user_ref_key, foreign_key: true
t.timestamps
end
end
end
db/schema.rb 的結果如下:
create_table "stores", force: :cascade do |t|
t.string "title"
t.string "address"
t.integer "user_int_id"
t.integer "user_int_index_id"
t.integer "user_int_key_id"
t.integer "user_ref_id"
t.integer "user_ref_index_id"
t.integer "user_ref_key_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_int_index_id"], name: "index_stores_on_user_int_index_id"
t.index ["user_ref_id"], name: "index_stores_on_user_ref_id"
t.index ["user_ref_index_id"], name: "index_stores_on_user_ref_index_id"
t.index ["user_ref_key_id"], name: "index_stores_on_user_ref_key_id"
end
可以看得出來:
- references 的寫法最後也是產生 integer 欄位,但會自動補上
_id
名稱(你有注意到嗎?)。 - 在純用 integer 的寫法中,需要主動告知
index: true
才會幫忙加索引,用forign_key
的方式不會。 - 用 references 的寫法,不管有沒有
index: true
,都會自動幫你加上索引。
那麼,foreign_key: true
的用途是什麼呢? 它是用來確保兩個資料表之間的資料完整性(data integrity),以我們上課舉的例子來說,每家商店都應該有一位店長。如果假設你手動從資料庫刪了一個店長,那麼該店長管的那間店就會變沒人管了...
所以 foreign_key: true
的用途,便是會在建立 table 的時候再加上這樣的限制,注意,這個限制是直接建立在 table 裡的喔,不是建立在抽象層的 Model。
而像 has_many
或是 belongs_to
之類的方法就是建立在抽象層 Model 之間的關係,有這樣的設定僅表示這兩個 Model 之間有多了一些方法可以互相查詢,但不表示他們在資料庫上就有直接的關連喔,這點要特別注意。
Model 跟 table 是兩個不一樣的東西,小心不要混在一起喔 :)