Ruby on rails Rails迁移:将_引用添加到表中,但外键的列名与Rails约定不同

Ruby on rails Rails迁移:将_引用添加到表中,但外键的列名与Rails约定不同,ruby-on-rails,rails-migrations,Ruby On Rails,Rails Migrations,我有以下两种型号: class Store < ActiveRecord::Base belongs_to :person end class Person < ActiveRecord::Base has_one :store end 类存储

我有以下两种型号:

class Store < ActiveRecord::Base
    belongs_to :person
end

class Person < ActiveRecord::Base
    has_one :store
end
类存储
问题是:我正在尝试创建一个迁移,以便在people表中创建外键。但是,引用Store外键的列并不像rails惯例那样命名为Store\u id,而是命名为foo\u bar\u Store\u id

如果我遵循rails约定,我会这样做迁移:

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

但是,这不起作用,因为列名不是store\u id,而是foo\u bar\u store\u id。那么,我如何指定外键名称只是不同,但仍然保持index:true以保持快速性能呢?

在封面下的add\u引用只是授权add\u列和add\u index,所以您只需要自己处理它:

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

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

虽然此答案实现了使用非常规外键列名的目标,但通过索引,它不会向数据库添加fk约束。有关使用
添加外键
和/或“添加参考”更合适的解决方案,请参见其他答案

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

原始答复:

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
class-Person
在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
请参阅和文档中有关关联选项的详细信息。

\Migration
换桌子:人们不会|
t、 参考:foo_bar_store,参考::store#->foo_bar_store_id
结束
#模型
#app/models/person.rb
类Person
在rails 5.x中,您可以向具有不同名称的表添加外键,如下所示:

class AddReferencesToPeople < ActiveRecord::Migration
  def change
    add_reference :people, :store, index: true
  end
end
class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
  def change
    add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
  end
end
class AddFooBarStoreToPeople
要扩展schpet的答案,这在
create_table
Rails 5迁移指令中起作用,如下所示:

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


Person模型如何知道foo_bar_store_id实际上是存储_id的外键?它不属于迁移,而是属于模型中的关联定义。正如Matt所提到的
有一个:存储,外键:'foo\u bar\u store\u id'
这不是数据库中的外键。@baash05您能解释一下您的问题吗?@Matt我想他是想问的,问题是专门询问如何在表(数据库级别)中创建外键,而不仅仅是在模型级别。我认为,在较新的rails 4.2中,生成的带有引用的迁移可以在适当的表中添加外键,以帮助确保数据完整性。格式有问题,但我认为相关的代码可能类似于
add_foreign\u key:people,:stores,column::foo\u bar\u store\u id
@RandyShelford谢谢,但我认为这也不能解释baash05的评论。我的答案包括通过migrate在数据库中创建外键,以及在模型中处理非标准外键。我的答案遗漏了什么?您关于添加外键的建议已经包含在这里的另一个答案中。@Matt为了澄清Randy/baash05的说法,这不会在数据库中创建外键约束。也就是说,
foo\u bar\u store\u id
可以设置为无效的store id,并且模型将通过所有验证。如果我错了,请纠正我,但只要在模型中添加该行,rails就不会在保存时抛出ActiveRecord::InvalidForeignKey:PG::ForeignKeyViolation:ERROR错误。应该“add\u column:people,:foo\u bar\u store\u id,index:true`声明类型?@alex true”—最好使用单独的up和down方法,而不是一个change方法。up可能看起来与答案的change方法相同,down可能会删除该列。@inye似乎该错误已被修复。这是一种似乎未记录的黑客行为,使我同时喜欢和讨厌Rails。这也适用于
create_table
方向,如:
t.references:feature,外键:{to_table::product_features}
爱恨关系是最好的,但如果数量合适,当我在MySQL中执行此操作时,我会得到ActiveRecord::MismatchedForeignKey:Column
传入位置\u id
在表
库存收入中
地址中的列
id
不匹配,其类型为
bigint(20)
。要解决此问题,请将
inventory\u incomings
上的
incoming\u location\u id
列的类型更改为:bigint。
t.references:novel,foreign\u key:{To\u table::books}
如中所示,但它没有说明或提及可用于外键的其他选项。这些选项可以在以下文档中找到:method@JigneshGohel感谢您链接到文档!我以前从未遇到过这种情况。很高兴有人也添加了模型参考;节省了我一些时间!
create_table :chapter do |t|
  t.references :novel, foreign_key: {to_table: :books}
  t.timestamps
end