Ruby-on-rails Rails 迁移:向表添加引用但外键的列名与 Rails 约定不同

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27809342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:02:48  来源:igfitidea点击:

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

ruby-on-railsrails-migrations

提问by Neil

I have the following two Models:

我有以下两个模型:

class Store < ActiveRecord::Base
    belongs_to :person
end

class Person < ActiveRecord::Base
    has_one :store
end

Here is the issue: I am trying to create a migration to create the foreign key within the people table. However, the column referring to the foreign key of Store is not named store_idas would be rails convention but is instead named foo_bar_store_id.

问题是:我正在尝试创建迁移以在 people 表中创建外键。但是,引用 Store 外键的列不像rails 约定那样命名为store_id ,而是命名为foo_bar_store_id

If I was following the rails convention I would do the migration like this:

如果我遵循 rails 约定,我会像这样进行迁移:

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

However this will not work because the column name is not store_idbut is foo_bar_store_id. So how do I specify that the foreign key name is just different, but still maintain index: true to maintain fast performance?

但是这不起作用,因为列名不是store_id而是foo_bar_store_id。那么如何指定外键名称不同,但仍然保持 index: true 以保持快速性能?

采纳答案by Matt

EDIT: For those that see the tick and don't continue reading!

编辑:对于那些看到勾而不继续阅读的人!

While this answer achieves the goal of having an unconventional foreign key column name, with indexing, it does not add a fk constraint to the database. See the other answers for more appropriate solutions using add_foreign_keyand/or 'add_reference'.

虽然这个答案实现了拥有非常规外键列名的目标,但它没有向数据库添加 fk 约束。有关使用add_foreign_key和/或“add_reference”的更合适解决方案,请参阅其他答案。

Note: ALWAYS look at the other answers, the accepted one is not always the best!

注意:总是看其他答案,被接受的并不总是最好的!

Original answer:

原答案:

In your AddReferencesToPeoplemigration you can manually add the field and index using:

在您的AddReferencesToPeople迁移中,您可以使用以下方法手动添加字段和索引:

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

And then let your model know the foreign key like so:

然后让您的模型知道外键,如下所示:

class Person < ActiveRecord::Base
  has_one :store, foreign_key: 'foo_bar_store_id'
end

回答by schpet

in rails 5.x you can add a foreign key to a table with a different name like this:

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

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

回答by Sia

In Rails 4.2, you can also set up the model or migration with a custom foreign key name. In your example, the migration would be:

在 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

Hereis an interesting blog post on this topic. Hereis the semi-cryptic section in the Rails Guides. The blog post definitely helped me.

是有关此主题的有趣博客文章。是 Rails 指南中的半隐秘部分。这篇博文肯定对我有帮助。

As for associations, explicitly state the foreign key or class name like this (I think your original associations were switched as the 'belongs_to' goes in the class with the foreign key):

至于关联,请像这样明确说明外键或类名(我认为您的原始关联已随着“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

Note that the class_name item must be a string. The foreign_key item can be either a string or symbol. This essentially allows you to access the nifty ActiveRecord shortcuts with your semantically-named associations, like so:

请注意, 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

See more about the association options in the documentation for belongs_toand has_one.

查看有关belongs_tohas_one文档中关联选项的更多信息。

回答by toobulkeh

To expand on schpet's answer, this works in a create_tableRails 5 migration directive like so:

为了扩展 schpet 的答案,这适用于create_tableRails 5 迁移指令,如下所示:

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

回答by Richard Peck

# 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

回答by boulder

Under the covers add_reference is just delegating to add_column and add_index so you just need to take care of it yourself:

在幕后 add_reference 只是委托给 add_column 和 add_index 所以你只需要自己照顾它:

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