TL;DR:提供to_table 选项,就像foreign_key: {to_table: :<table_name>} 。
当涉及到为一个belongs_to 关联的Rails迁移时,如果其名称与连接表的名称不一致,在阅读Rails文档或资料后,可能很难迅速找到如何做。这篇文章应该能帮到你。
让我们从下面的例子开始:
- 系统中已经有了一个
User模型 - 我们需要添加
Payment模型 Payment应该属于一个 ,也就是 。receiverUser
在代码中,它会看起来像这样:
class User < ApplicationRecord
end
class Payment < ApplicationRecord
belongs_to :receiver, class_name: 'User'
end
让我们试着生成一个这个模型和一个迁移,按照文档的要求为它创建DB表:
rails g model payment receiver:references
这就产生了下面的迁移:
class CreatePayments < ActiveRecord::Migration[6.0]
def change
create_table :payments do |t|
t.belongs_to :receiver, null: false, foreign_key: true
t.timestamps
end
end
end
令人惊讶的是,rake db:migrate 产生了以下错误:
PG::UndefinedTable: ERROR: relation "receivers" does not exist
原因很明显。这个迁移试图为一个不存在的表添加一个外键。它采用了关联名receiver ,并且默认为它指向一个复数的表receivers 。这并没有什么问题。除了一个事实,就是没有receivers 表,应该用users 表来代替。
不幸的是,在花了大量时间阅读文档后,人们甚至可能最终没有解决方案。在Rails代码的深处,很难发现例子中的某一行。因此,我在这里提供了一个解决方案:
class CreatePayments < ActiveRecord::Migration[6.0]
def change
create_table :payments do |t|
t.belongs_to :receiver, null: false, foreign_key: {to_table: :users}
t.timestamps
end
end
end
现在迁移运行时没有出现任何故障,并且产生了一个正确的结果,即创建的payments 表带有receiver_id 列和一个外键指向加入的users 表。
因此,解决方案是在上面的例子中使用foreign_key: {to_table: :users} 。