Skip to content

Instantly share code, notes, and snippets.

@kaochenlong
Last active September 14, 2021 01:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaochenlong/c633228d1fdc97d3ba6212af14904be6 to your computer and use it in GitHub Desktop.
Save kaochenlong/c633228d1fdc97d3ba6212af14904be6 to your computer and use it in GitHub Desktop.

其實 index: trueforeign_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

可以看得出來:

  1. references 的寫法最後也是產生 integer 欄位,但會自動補上 _id 名稱(你有注意到嗎?)。
  2. 在純用 integer 的寫法中,需要主動告知 index: true 才會幫忙加索引,用 forign_key 的方式不會。
  3. 用 references 的寫法,不管有沒有 index: true,都會自動幫你加上索引。

那麼,foreign_key: true 的用途是什麼呢? 它是用來確保兩個資料表之間的資料完整性(data integrity),以我們上課舉的例子來說,每家商店都應該有一位店長。如果假設你手動從資料庫刪了一個店長,那麼該店長管的那間店就會變沒人管了...

所以 foreign_key: true 的用途,便是會在建立 table 的時候再加上這樣的限制,注意,這個限制是直接建立在 table 裡的喔,不是建立在抽象層的 Model。

而像 has_many 或是 belongs_to 之類的方法就是建立在抽象層 Model 之間的關係,有這樣的設定僅表示這兩個 Model 之間有多了一些方法可以互相查詢,但不表示他們在資料庫上就有直接的關連喔,這點要特別注意。

Model 跟 table 是兩個不一樣的東西,小心不要混在一起喔 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment