Rails 3迁移:是否添加参考列?


161

如果我使用以下方式创建新的Rails 3迁移:

rails g migration tester title:tester user:references

,一切正常...但是,如果我添加一列内容如下的内容:

rails g migration add_user_to_tester user:references

无法识别参考字段。简而言之,问题是:如何从命令行向Rails迁移添加引用列?

Answers:


205

如果您使用的是Rails 4.x,现在可以使用引用生成迁移,如下所示:

rails generate migration AddUserRefToProducts user:references

就像在导轨上看到的一样



2
如何为外键指定列名称,而不是自动生成的名称?
j将

@jwill您可以使用多态的:user:references {polymorphic}。
Paulo Fidalgo 2015年

@PauloFidalgo您能解释一下该怎么做吗?可能是一些链接的指南?(谈论多态)
Anwar


186

编辑:这是一个过时的答案,不应应用于Rails 4.x +

可以在引用的类中使用整数id时,无需添加引用。

我要说的是,使用引用而不是普通整数的优势在于,该模型将使用belongs_to进行预定义,并且由于该模型已经创建,并且在迁移现有内容时不会受到影响,因此目的就有些丢失了。

因此,我想这样做:

rails g migration add_user_id_to_tester user_id:integer

然后在Tester模型中手动添加belongs_to:user


9
但这不会在支持它的数据库上创建适当的外键约束,对吗?
2011年

19
不,afaik Rails永远不会在数据库上创建外键约束,除非您添加插件来为您做。
DanneManne

只是研究这篇文章,请问我到底该如何添加参考资料
El nino 2012年

13
记得用user:integer:index添加索引
rickypai 2012年

3
答案是过时的,请参阅@Paulo对于现代Rails的答案。
OneHoopyFrood 2015年

102

请注意,您很可能也需要在该列上建立索引。

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end

1
为什么?对于大多数belongs_to关系,这是真的吗?
ahnbizcad 2014年

确实是出于性能方面的考虑,如果在属属关系的另一侧具有has_many / has_one,它会派上用场。如果您完全确定不会通过user.testers,则可以省略索引。
尤金2014年

1
rails g migration ...产生add_reference :installs, :device, index: true,其还创建索引。
B 2014年

49

通过上述前面的两个步骤,您仍然缺少外键约束。这应该工作:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end

这是这里唯一的实际答案。外键是这里最关键的部分
user2490003

这应该标记为正确答案,因为问题要求使用“ rails 3”
Carlos Roque'May

35

可以在变更迁移中使用参考。这是有效的Rails 3.2.13代码:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf:http : //apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table


1
变化和下降的方法?不是上下方法吗?
MaicolBen 2015年

@MaicolBen是的,您也可以不使用down方法。
Hut8

@MaicolBen如果没有该down方法,则ActiveRecord::IrreversibleMigration在使用Rails 3.2回滚时会遇到。我还必须更改changeup
Andrew Grimm'3

27

运行rails g migration AddUserRefToSponsors user:references将生成以下迁移:

def change
  add_reference :sponsors, :user, index: true
end

这是哪个版本的Rails?
Andrew Grimm'3

8

添加列时,您需要将该列设置为整数,并尽可能遵循rails约定。因此,对于您的情况,我假设您已经有一个Tester和User模型,以及testers和users表。

要添加外键,您需要创建一个名称为user_id(约定)的整数列:

add_column :tester, :user_id, :integer

然后向测试器模型添加一个belongs_to:

class Tester < ActiveRecord::Base
  belongs_to :user
end

并且您可能还想为外键添加索引(这是引用已经为您完成的操作):

add_index :tester, :user_id

8

这将达到目的:

rails g migration add_user_to_tester user_id:integer:index

我喜欢这样,它还会添加您最可能需要的索引。
bheeshmar

3

您可以通过以下方式通过命令行添加对模型的引用:

rails g migration add_column_to_tester user_id:integer

这将生成一个迁移文件,例如:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

每次我使用它都可以正常工作。


3

对于Rails 4

生成器接受列类型作为引用(也可作为belongs_to)。

此迁移将创建一个user_id列和适当的索引:

$ rails g migration AddUserRefToProducts user:references 

产生:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

对于Rails 3

帮助程序称为引用(也可以作为参考belongs_to)。

此迁移将创建category_id适当类型的列。请注意,您传递的是模型名称,而不是列名称。Active Record _id为您添加。

change_table :products do |t|
  t.references :category
end

如果您具有多态belongs_to关联,则引用将添加所需的两列:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

将添加一个attachment_id列和attachment_type一个默认值为的字符串列Photo

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.