在活动记录中添加自动递增列

时间:2014-05-30 17:54:23

标签: ruby-on-rails postgresql activerecord

我试图在postgresql中向我的表中添加一个基于整数的自动递增列,然后通过活动记录访问它。它通过活动记录保持设置为NULL。

明显的方法:

add_column :table_name, :id_name, :primary_key

这不起作用,因为该表已有主键。

接下来,我尝试将其添加到Active Record迁移的上一部分:

execute("ALTER TABLE table_name ADD id_name SERIAL;")

这在创建表时非常有效,如果我通过db直接创建新条目,则id_name设置为人们希望的。但是,如果我通过使用.new& amp;来通过ActiveRecord创建一个新条目。 .save或.create在尝试将id_name设置为null时会爆炸。

我也尝试过:

execute("CREATE SEQUENCE table_name_id_name_seq;")
execute("ALTER TABLE table_name ADD id_name INTEGER DEFAULT NEXTVAL('table_name_id_name_seq');")
execute("ALTER SEQUENCE table_name_id_name_seq OWNED BY table_name.id_name;")

允许.new& .save以及.create来创建一个条目,但结果的id_name为null。

有没有办法说服Rails不要用null覆盖默认的db值?

2 个答案:

答案 0 :(得分:0)

有点hacky,但这是一个有效的解决方案:

def up   
  add_column :table_name, :id_name, :integer
  n = 1
  TableName.all.each_with_index do |name|
    name.id_name = n
    name.save
    n += 1
  end
  execute "CREATE SEQUENCE table_name_id_name_seq START #{n} OWNED BY table_name.id_name;"
end


def next_seq_value(sequence)
  Article.connection.execute("SELECT nextval('#{sequence}')")[0]['nextval']
end


before_validation(:on => :create) do
  unless attribute_present?("id_name")
    self.id_name = next_seq_value('table_name_id_name_seq')
  end
 end

答案 1 :(得分:-1)

使用类型serial使数据库自动增加列的问题是schema.db不支持它,因此您无法使该功能填充测试数据库,例如

相反,这是一种支持递增列的数据库无关的方法:

  before_create :increment_identifier

  def increment_identifier
    sql = "SELECT COALESCE(MAX(identifier), 0) + 1 FROM claims"
    self.identifier = ActiveRecord::Base.connection.execute(sql).values[0][0]
  end

对于空表,COALESCE只返回0而不是nil。 values[0][0]是访问ActiveRecord.Base返回的时髦对象的必要方法。