在Rails / Postgres中使用字符串主键时,我应该删除默认的“id”字段吗?

时间:2012-07-20 13:44:10

标签: ruby-on-rails postgresql activerecord heroku

这是问题I asked before的构建(没有任何运气)。

我有一个模型,我使用字符串作为主键:

class Employee < ActiveRecord::Base
   self.primary_key = "employment_id"
end 

此表还包含Rails默认的“id”字段,具有唯一性约束。

当我在本地添加新员工时,一切正常,Rails会自动生成一个新的唯一ID。

然而,当我在Heroku Postgres上运行它时,似乎将'id'和'employment_id'视为同一个字段。我尝试通过手动设置唯一ID来解决这个问题,但仍然会出现这种情况:

Employee.new do |s|

  max_id = Employee.maximum(:id)  
  puts max_id.to_s             # => 1803 

  s.employment_id = "fred_01"      
  s.id = max_id + 1 

  puts employment_id.to_s      # => 1804

end

我在本地运行postgres 9.1.3(Heroku在9.1.4上运行)。我在Rails 3.2.3上。

我的问题是:

  • 知道这里发生了什么吗?
  • 你认为我使用employment_id作为主键是对的吗?
  • 如果我删除了'id'字段会有帮助吗?
  • 您会推荐其他最佳做法吗?

感谢您的帮助!

德里克。

修改

按要求添加迁移文件:

class CreateEmployees < ActiveRecord::Migration
  def change
    create_table :employees do |t|
      t.string :employment_id, :unique => true
      etc...
    end
  end
end

修改

很多人没有人指出这一点,但我现在很清楚,真正的答案是“只因为你可以,并不意味着你应该!”

2 个答案:

答案 0 :(得分:1)

根据this帖子,它应该解决问题:

class CreateEmployees < ActiveRecord::Migration
  def change
    create_table :employees, {:id => false} do |t|
      t.string :employment_id, :unique => true
      etc...
    end
  end
  execute "ALTER TABLE employees ADD PRIMARY KEY (employment_id);"
end

同样在你的模特中:

class Employee < ActiveRecord::Base
  set_primary_key :employment_id
  ...
end

答案 1 :(得分:1)

Rails 4.2.0和Postgres的更新,以防有人帮助......

id: :string选项中添加create_table

class FooMigration < ActiveRecord::Migration
  def change
    create_table :foo, id: :string do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
  end
end

rake db:migrate

== 20150225043441 FooMigration: migrating ===========================
-- create_table(:foo, {:id=>:string})    -> 0.0031s
== 20150225043441 FooMigration: migrated (0.0032s) ==================

rails db(和\ d foo)

psql (9.3.6)
Type "help" for help.

bar_development=# \d foo
                  Table "public.foo"
   Column   |            Type             | Modifiers 
------------+-----------------------------+-----------
 id         | character varying           | not null
 name       | character varying           | not null
 created_at | timestamp without time zone | not null
 updated_at | timestamp without time zone | not null
Indexes:
    "foo_pkey" PRIMARY KEY, btree (id)

我最终得到一个带有主键索引的'not null'字符串列。

更多地使用id以外的列名。

编辑(2015年2月26日):在生成schema.rb文件时,rails中似乎存在错误。它不会记录自定义主键状态,您需要进入并编辑它以将id: :string选项添加到create_table调用。

create_table "foo", id: :string, force: :cascade do |t|
  t.string   "name",       null: false
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

糟糕的部分:每次迁移都会撤消该更改。你必须密切关注文件内容(或写一个测试:))。

该错误已在PR 18228中修复,并于2015年1月3日合并到rails:master。