【问题标题】:Heroku, Postgresql, composite_primary_keysHeroku、Postgresql、composite_primary_keys
【发布时间】:2012-06-06 04:42:41
【问题描述】:

我正在开发一个 Rails 3 应用程序。我在几个表中使用了composite_primary_keys gem,但是Rails 仍在创建一个没有被使用的id 字段(即每个条目都为nil)。虽然它在 SQLite3 中的本地计算机上运行,​​但我无法在 Heroku 上运行该应用程序。 Postgresql 对我大发雷霆,并给了我这个错误:

2012-05-31T21:12:36+00:00 app[web.1]: ActiveRecord::StatementInvalid (PG::Error: ERROR:  null value in column "id" violates not-null constraint
2012-05-31T21:12:36+00:00 app[web.1]:   app/controllers/items_controller.rb:57:in `block (2 levels) in create'
2012-05-31T21:12:36+00:00 app[web.1]: : INSERT INTO "item_attr_quants" ("attribute_id", "created_at", "id", "item_id", "updated_at", "value") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "item_id","attribute_id"):

由于“id”字段为 nil,Postgresql 对我大喊大叫。

有没有一种方法可以防止“id”字段被创建,使用原始 SQL 语句删除列,强制 Heroku 上的 Postgresql 允许“id”字段为空,或者绕过这是其他方式吗?我对使用复合主键很执着,所以我不想删除 gem 并重写代码。

型号

class ItemAttrQuant < ActiveRecord::Base
  belongs_to :item
  belongs_to :attribute
  self.primary_keys = :item_id, :attribute_id
end

迁移

class CreateItemAttrQuants < ActiveRecord::Migration
  def change
    create_table :item_attr_quants do |t|
      t.belongs_to :item
      t.belongs_to :attribute
      t.integer :value

      t.timestamps
    end
    add_index :item_attr_quants, :item_id
    add_index :item_attr_quants, :attribute_id
  end
end

【问题讨论】:

  • 我的答案被删除了,因为它没有回答问题,但它确实没有回答。然而,针对一个数据库进行开发并部署到另一个数据库是一个非常糟糕的主意。这就像使用 ruby​​ 1.8.6 开发并部署到 1.9.3。当然,界面大多相同,但并不相同。如果您继续走这条路,这个问题是您将遇到的许多问题中的第一个问题。
  • 威尔,感谢您对一般开发的有用建议。我有点搞砸了,但我想这是作为新开发人员学习曲线的一部分。

标签: ruby-on-rails ruby postgresql activerecord heroku


【解决方案1】:

您可以在迁移中对create_table 使用:id =&gt; false:primary_key 选项:

class CreateItemAttrQuants < ActiveRecord::Migration
  def change
    create_table :item_attr_quants, :id => false do |t|
      ...
    end
    ...
  end
end

这将创建没有id 列的item_attr_quants,但您的表将没有真正的主键。您可以通过为item_idattribute_id 指定not null 并在这两列上添加唯一索引来添加假的:

class CreateItemAttrQuants < ActiveRecord::Migration
  def change
    create_table :item_attr_quants, :id => false do |t|
      t.integer :item_id, :null => false
      t.integer :attribute_id, :null => false
      t.integer :value
      t.timestamps
    end
    add_index :item_attr_quants, [:item_id, :attribute_id], :unique => true
    add_index :item_attr_quants, :item_id
    add_index :item_attr_quants, :attribute_id
  end
end

我不认为 ActiveRecord 完全理解数据库中真正的复合主键的概念,因此除非您想手动将 ALTER TABLE 发送到数据库中,否则唯一索引是 AFAIK 的最佳选择。

【讨论】:

  • 感谢您的彻底回复!它工作得很好。我没有考虑过在 Rails 数据库中不创建 id 字段是可能的。
猜你喜欢
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 2017-07-12
  • 2011-09-13
  • 2017-08-10
  • 2015-11-29
相关资源
最近更新 更多