向现有的Rails模型添加模型引用

28

我想知道在Rails 3中添加两个已存在类之间关系的“正确”方法。

给定现有模型:Clown 和 Rabbit

我想要从 Rabbit 添加一个引用(belongs_to)到 Clown。我会尝试生成一个迁移文件来实现:

rails g migration AddClownToRabbits clown:reference

这使我得到了一个看起来像这样的迁移:

class AddClownToRabbits < ActiveRecord::Migration
  def self.up
    add_column :rabbits, :clown, :reference
  end

  def self.down
    remove_column :rabbits, :clown
  end
end

在运行rake db:migrate后,在SQLite3的development.db中我看到出现了一个新列:"clown" reference

我猜我期望看到的是一个"clown_id" integer列和如下迁移:

class AddClownToRabbits < ActiveRecord::Migration
  def self.up
    add_column :rabbits, :clown_id
  end

  def self.down
    remove_column :rabbits, :clown_id
  end
end

我相信:reference应该等同于"t.references :clown",但我找不到文档(大惊小怪)。API说add_column:为表格实例化一个新列。type参数通常是迁移原生类型之一,它是以下类型之一::primary_key、:string、:text、:integer、:float、:decimal、:datetime、:timestamp、:time、:date、:binary、:boolean。

...没有提及对:reference的引用。


1
关于文档(如果算作文档的话),请参见http://guides.rubyonrails.org/getting_started.html,向下滚动到7.1生成模型并查看该标题下方的代码片段。您会发现那里使用的是“*:references*”而不是“*:reference*”。 - iconoclast
3个回答

64

如果您使用的是Edge Rails(4.0),您可以使用以下内容:

rails generate migration AddAddressRefToContacts address:references

如你所见,根据文档


3
终于!自 Rails 2 以来就一直缺少这个。 - paul.ago
如果你喜欢的话,你也可以使用address:belongs_to - chad_
该程序相关内容的翻译如下:应该使用原始示例。 - Daniel Viglione

18

在你设置了Rabbit的belongs_to和Clown的has_many之后,你可以进行以下迁移:

add_column :rabbit, :clown_id, :integer

编辑:请参考以下 Paulo 的答案,以获取更更新的答案(适用于 Rails 4+)


太棒了!谢谢!我有点预料到了,但还在苦苦挣扎着该把它放在哪里……在一个“裸”迁移中吗?也许只需要rails g migration AddClownToRabbits,然后手动编辑剩余的部分? - Meltemi
我刚刚测试了一下,它确实给了我一个带有正确时间戳文件名的空白板,我可以像你提到的那样进行编辑。谢谢。 - Meltemi
1
我认为使用“引用”也会向列添加索引,但这种方式需要添加:index => true。类似这样:add_reference :rabbits, :clown, :index => true - TheJKFever

5
我不确定你从哪里得到这个想法,但是没有(也从未有过)这样的语法来完成你想要的add_column操作。要获得所需的行为,您需要执行t.references :clown,就像您所述一样。在后台,这将调用:@base.add_column(@table_name, "#{col}_id", :integer, options)
请参见此处
编辑:
我想我可以看出你困惑的源头了。你看到了方法调用t.reference并认为它是一种数据类型,因为存在诸如t.integert.string之类的调用,这些都是数据类型。这是错误的。引用不是数据类型,只是一个方法的名称,类似于t.rename

抱歉造成困惑...学习中...这就是学习的方式。谢谢!那么,回答我的问题,什么是正确的生成器命令...我仍然假设需要从一个开始,因为生成器是有时间戳的,我不认为应该手动创建文件名?!?rails g migration AddClownToRabbits clown:reference给我上面的错误垃圾。 - Meltemi
@Meltemi:没有添加引用的生成器命令,只有列。请记住,生成器所做的就是生成...嗯...生成而已。它不能添加引用并不是什么大不了的事情,你只需要自己添加即可。 - ryeguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接