0

这是基于我之前提出的一个问题(没有任何运气)。

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

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

编辑

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

4

2 回答 2

1

Rails 4.2.0 和 Postgres 的更新,以防它帮助任何人......

将 aid: :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

耙分贝:迁移

== 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)

我最终得到一个带有主键索引的“非空”字符串列。

使用除以外的列名id更复杂。

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

IE。

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。

于 2015-02-25T05:59:51.767 回答
1

根据这篇文章,它应该可以解决问题:

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
于 2012-07-20T14:44:20.273 回答