如何在Ruby on Rails 5.2中的ActiveRecord迁移中创建表时定义使用的顺序?

时间:2018-10-13 00:12:35

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

我需要为表的ID字段分配一个特定的Postgres序列。在模型中,我尝试定义以下对Posgres没有影响的设置:

  

MyObject类      

self.sequence_name =“ global_seq”

通常,ActiveRecord迁移中的表定义以

开始
create_table "objects", id: :serial, force: :cascade do |t|

生成Postgres列默认值的定义为

default nextval('objects_id_seq'::regclass)

如何在迁移中指定nextval()函数应依赖另一个序列?

3 个答案:

答案 0 :(得分:3)

您可以在迁移中更改默认设置:

change_column :my_objects, :id, :integer, default: -> { "nextval('global_seq')" }

您可能希望使用:bigint而不是:integer,具体取决于顺序和表的设置方式。您必须对:default选项使用lambda才能将原始nextval('global_seq')表达式获取到数据库中。

您可能还希望删除旧序列,因此您必须使用connection.execute('drop sequence ...')

如果您跳过:id中的默认create_table步骤,则可以在手动创建:id列时完成所有操作:

create_table :my_objects, id: false do |t|
  t.bigint :id, null: false, default: -> { "nextval('global_seq')" }
  t.primary_key :id
  ...
end

同样,t.bigintt.integer之间的选择取决于您希望PK的大小。

答案 1 :(得分:1)

恐怕Rails的迁移没有内置命令来显式设置列的顺序。这是非常特定于数据库的。

但是可以使用普通SQL来完成:

class ChangeSequenceOfObjectId < ActiveRecord::Migration[5.0]
  def self.up
    execute <<-SQL
      CREATE SEQUENCE global_seq;
      ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('global_seq');
      ALTER SEQUENCE objects_id_seq OWNED BY NONE;
      ALTER SEQUENCE global_seq OWNED BY objects.id;
    SQL
  end

  def self.down
    execute <<-SQL
      ALTER TABLE objects ALTER COLUMN id SET DEFAULT nextval('objects_id_seq');
      ALTER SEQUENCE objects_id_seq OWNED BY objects.id;
      ALTER SEQUENCE global_seq OWNED BY NONE;
      DROP SEQUENCE global_seq;
    SQL
  end

如果在其他迁移中创建了global_seq序列,则只需删除有关其创建/删除的相应行即可。

如果您想将ALTER SEQUENCE global_seq OWNED BY序列保留为“独立式”(即使删除了global_sql表,也可以保留在db中),也可以删除objects命令。

答案 2 :(得分:0)

我使用sequence_name选项(Rails 5.1):

create_table "opjects", sequence_name: 'global_seq' do |t|

我没有检查,但是我猜想,在Rails 5.2中也应该起作用。