Rails 迁移创建表的主键

17

我正在编写一个迁移脚本,以创建一个名为guid的主键列,并且该列是VARCHAR(25)。问题是我感觉我需要付出双倍的努力才能完成应该在一步中完成的事情。

如果我运行:

create_table(:global_feeds, :primary_key => 'guid') do |t|
  t.string :guid, :limit => 25
  t.text :title
  t.text :subtitle

  ...

  t.timestamps
end

我拿到了一张名为guid的主键表,没有叫做id的列(这正是我所想要的)。然而问题在于,guid列是一个带有自动增量的INT(11)类型。因此,我需要运行一个额外的命令:
change_column :global_feeds, :guid, :string, :limit => 25

似乎需要运行两个SQL命令才能获得我认为应该在一个命令中实现的结果,这有点复杂。

有没有优化的建议?

5个回答

29
在Rails 4中,您可以这样做:
create_table :global_feeds, id: false do |t|
  t.string :guid, primary_key: true
 ...
end

2
这不应该是一个字符串,使用UUID的MySQL应该是二进制(16)。 - Seed

23

我猜你正在使用MySQL,所以这里是你可以尝试的方法:

create_table :global_feeds, {:id => false} do |t|
  t.string :guid
  t.text :title
  t.text :subtitle
  t.timestamps
end
execute "ALTER TABLE global_feeds ADD PRIMARY KEY (guid);"

如果您不使用 MySQL,您应该更改在execute命令中的查询以适用于您的数据库引擎。虽然我不确定您是否可以在SQLite上这样做。并且请不要忘记将此行放置在 global_feed.rb 模型的某个位置:

set_primary_key :guid

在遵循Rails的规范时,您可以充分利用它。更改主键名称和类型可能不是一个非常好的主意。


不幸的是,这仍然是两个像我的SQL语句。您只是翻转了操作顺序:首先定义列类型,然后指定主键。 - Ryan
我猜你不能用一个操作完成这个任务,但我觉得这并没有什么问题。对于更加复杂的情况,迁移有两个语句是完全可以的。 - Max Al Farakh
我也不确定ActiveRecord是否能够很好地处理非整数主键。 - Max Al Farakh
我会为你的努力点个赞,maxt3r。感谢你的尝试。 - Ryan
1
我遇到了一个处理继承模式的问题;我尝试使用primary_key的几乎所有可能的组合以及其他相关问题中提出的大部分建议。在Rails 3.2.x与MySQL上,这个解决方案是可行的。需要注意的一个关键问题是:rake db:schema:dump不会产生所需的输出(db:structure:dump可以)。回应@MaxAlFarakh的评论:更改主键名称和类型并不是一个好主意 :-| - Tom Harrison

4
您需要使用 #column 而不是 #string。例如:
create_table(:global_feeds, :primary_key => 'guid') do |t|
  t.column :guid, "varchar(25)", :null => false
  ...
end

请注意,varchar类型不适用于MySQL以外的其他数据库。


语法错误,意外的'(',期望关键字_end t.column :guid, :varchar(26),:null => false`,它指向varchar末尾的括号 - Ryan
没错,使用 "varchar(25)" 替代 :varchar(25) - JellicleCat
你也可以只使用 :string 类型,并将 limit: 25 设置为此示例的选项。 - RSmithlal

3

在Rails 3中,这是可能的。尝试使用以下代码:

  def self.up
    create_table(:signups, :id => false) do |t|
      t.string :token, :primary => true

请查看此代码片段,它提供了一种使用UUID作为主键列的好方法:https://gist.github.com/937739


请查看@kakoni的答案。 - the_drow

1
在Rails 5中,对于那些在使用从@kakoni得到的迁移时,在运行rails db:setup时遇到ArgumentError: Index name '*' on table '*' already exists问题的人,以下方法适用于我。
create_table(:global_feeds, primary_key: :guid, id: false) do |t|
  t.string :guid
 ...
end

了解更多信息,请查看create_table


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