簡體   English   中英

Rails 遷移:添加對表的引用,但外鍵的列名與 Rails 約定不同

[英]Rails Migration: add_reference to Table but Different Column Name For Foreign Key Than Rails Convention

我有以下兩個模型:

class Store < ActiveRecord::Base
    belongs_to :person
end

class Person < ActiveRecord::Base
    has_one :store
end

這是問題所在:我正在嘗試創建遷移以在 people 表中創建外鍵。 但是,引用 Store 外鍵的列沒有按照 rails 約定命名為store_id ,而是命名為foo_bar_store_id

如果我遵循 Rails 慣例,我會像這樣進行遷移:

class AddReferencesToPeople < ActiveRecord::Migration
  def change
    add_reference :people, :store, index: true
  end
end

但是,這將不起作用,因為列名不是store_id而是foo_bar_store_id 那么如何指定外鍵名稱只是不同,但仍保持 index: true 以保持快速性能?

在Rails 4.2中,您還可以使用自定義外鍵名稱設置模型或遷移。 在您的示例中,遷移將是:

class AddReferencesToPeople < ActiveRecord::Migration
  def change
    add_column :people, :foo_bar_store_id, :integer, index: true
    add_foreign_key :people, :stores, column: :foo_bar_store_id
  end
end

是一篇關於這個主題的有趣博客文章。 是Rails指南中的半隱藏部分。 這篇博文絕對幫助了我。

對於關聯,顯式地聲明這樣的外鍵或類名(我認為你的原始關聯被切換為'belongs_to'在具有外鍵的類中):

class Store < ActiveRecord::Base
  has_one :person, foreign_key: :foo_bar_store_id
end

class Person < ActiveRecord::Base
  belongs_to :foo_bar_store, class_name: 'Store'
end

請注意,class_name項必須是字符串。 foreign_key項可以是字符串或符號。 這實際上允許您使用語義命名的關聯訪問漂亮的ActiveRecord快捷方式,如下所示:

person = Person.first
person.foo_bar_store
# returns the instance of store equal to person's foo_bar_store_id

有關belongs_tohas_one文檔中的關聯選項的更多信息,請參閱。

在rails 5.x中,您可以將外鍵添加到具有不同名稱的表中,如下所示:

class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
  def change
    add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
  end
end

編輯:對於那些看到勾號並且不繼續閱讀的人!

雖然這個答案實現了具有非常規外鍵列名稱的目標,但通過索引, 它不會向數據庫添加fk約束 有關使用add_foreign_key和/或'add_reference'的更合適的解決方案,請參閱其他答案。

注意:總是看看其他答案,接受的答案並不總是最好的!

原始答案:

AddReferencesToPeople遷移中,您可以使用以下方法手動添加字段和索引:

add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id

然后讓你的模型像這樣知道外鍵:

class Person < ActiveRecord::Base
  has_one :store, foreign_key: 'foo_bar_store_id'
end
# Migration
change_table :people do |t|
  t.references :foo_bar_store, references: :store #-> foo_bar_store_id
end

# Model
# app/models/person.rb
class Person < ActiveRecord::Base
  has_one :foo_bar_store, class_name: "Store"
end

為了擴展schpet的答案,這適用於create_table Rails 5遷移指令,如下所示:

create_table :chapter do |t|
  t.references :novel, foreign_key: {to_table: :books}
  t.timestamps
end

在封面下,add_reference只是委托給add_column和add_index,所以你只需要自己處理:

add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id

具有不同列名的外鍵

add_reference(:products, :supplier, foreign_key: { to_table: :firms })

參考文檔Docs

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM