在Migration PostgreSQL上设置主键值0和自动增量

时间:2012-09-04 04:56:59

标签: ruby-on-rails ruby-on-rails-3 postgresql

我有一个带有2个字段的模型=> :姓名和:年龄

我需要做一个添加列的迁移:需要自动增量的位置,以0(零)开始。

我试过这种方式:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :integer, :default => 0, :null => false
    execute "ALTER TABLE clientes ADD PRIMARY KEY (position);"
  end

但它不起作用,因为它不会自动增加。如果我尝试使用主键作为类型:

class AddPosition < ActiveRecord::Migration
  def up
    add_column :clientes, :position, :primary_key, :default => 0, :null => false
  end
end

rake db:migrate因为有多个值而无法运行。

任何人都可以解释一下在主键上使用零和自动增量的方法w / Rails 3.2?

1 个答案:

答案 0 :(得分:2)

以下是在PostgreSQL中设置自动增量列的方法:

# in migration:
def up
  execute <<-SQL
    CREATE SEQUENCE clients_position_seq START WITH 0 MINVALUE 0;
    ALTER TABLE clients ADD COLUMN position INTEGER NOT NULL DEFAULT nextval('clients_position_seq');
  SQL
end

但不幸的是,它可能不是你需要的。如果您使用SQL将clients表中的值插入INSERT INTO clients(name, age) VALUES('Joe', 21),并且rails不能以这种方式工作,则上述操作将起作用。

第一个问题是rails期望主键被调用id。虽然你可以覆盖这个约定,但它会导致比它解决的问题更多的问题。如果要将位置绑定到主键值,更好的选择是将虚拟属性添加到模型中,如下所示:

def position
  id.nil? ? nil : id - 1
end

但我们假设您已经拥有传统的主键id,并希望添加position字段,以便您可以在创建客户端后对其进行重新排序,不用触摸其ID (这总是一个好主意)。第二个问题出现了:rails不会识别并尊重DEFAULT nextval('clients_position_seq'),即它不会从PG支持的序列中提取值,并且会默认将NULL放在position中。 / p>

我建议将acts_as_list gem视为更好的选择。这将使DB序列操作变得不必要。不幸的是,它使用1作为position的初始值,但可以通过设置列表位置字段的自定义名称并定义上面显示的方法来解决这个问题。