Rails 迁移:add_reference 到 Table 但外键的列名与 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
这是问题所在:我正在尝试创建迁移以在人员 table 中创建外键。但是,引用 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 以保持快速性能?
在幕后 add_reference 只是委托给 add_column 和 add_index 所以你只需要自己处理:
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
编辑:对于那些看到勾号但不继续阅读的人!
虽然这个答案实现了具有非常规外键列名的目标,但通过索引,它不会向数据库添加 fk 约束。使用 add_foreign_key
and/or '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
在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
Here is an interesting blog post on this topic. Here 是 Rails 指南中的半神秘部分。博客 post 绝对帮助了我。
至于关联,像这样明确说明外键或 class 名称(我认为您原来的关联已切换,因为 'belongs_to' 进入 class 与外键):
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 and has_one 的文档中查看有关关联选项的更多信息。
# 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
在 rails 5.x 中,您可以将外键添加到具有不同名称的 table 中,如下所示:
class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
def change
add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
end
end
在create_table
块内
t.references :feature, foreign_key: {to_table: :product_features}
为了扩展 schpet 的答案,这适用于 create_table
Rails 5 迁移指令,如下所示:
create_table :chapter do |t|
t.references :novel, foreign_key: {to_table: :books}
t.timestamps
end
我有以下两个模型:
class Store < ActiveRecord::Base
belongs_to :person
end
class Person < ActiveRecord::Base
has_one :store
end
这是问题所在:我正在尝试创建迁移以在人员 table 中创建外键。但是,引用 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 以保持快速性能?
在幕后 add_reference 只是委托给 add_column 和 add_index 所以你只需要自己处理:
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
编辑:对于那些看到勾号但不继续阅读的人!
虽然这个答案实现了具有非常规外键列名的目标,但通过索引,它不会向数据库添加 fk 约束。使用 add_foreign_key
and/or '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
在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
Here is an interesting blog post on this topic. Here 是 Rails 指南中的半神秘部分。博客 post 绝对帮助了我。
至于关联,像这样明确说明外键或 class 名称(我认为您原来的关联已切换,因为 'belongs_to' 进入 class 与外键):
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 and has_one 的文档中查看有关关联选项的更多信息。
# 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
在 rails 5.x 中,您可以将外键添加到具有不同名称的 table 中,如下所示:
class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
def change
add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
end
end
在create_table
块内
t.references :feature, foreign_key: {to_table: :product_features}
为了扩展 schpet 的答案,这适用于 create_table
Rails 5 迁移指令,如下所示:
create_table :chapter do |t|
t.references :novel, foreign_key: {to_table: :books}
t.timestamps
end