[英]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_to和has_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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.