Как определить последовательность для использования при создании таблицы в миграции ActiveRecord в Ruby on Rails 5.2? - PullRequest
0 голосов
/ 13 октября 2018

Мне нужно назначить определенную последовательность Postgres для поля ID моей таблицы.В модели я попытался определить следующую настройку, которая не влияет на Posgres:

class MyObject

self.sequence_name = "global_seq"

Как правило, определение таблицы в миграциях ActiveRecord начинается с

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

, которое генерирует в Postgres определение значения по умолчанию для столбца как

default nextval('objects_id_seq'::regclass)

Как указать вМиграция, что функция nextval () должна полагаться на другую последовательность?

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Вы можете изменить значение по умолчанию при миграции:

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

Возможно, вы захотите использовать :bigint вместо :integer в зависимости от того, как настроены ваша последовательность и таблицы.Вы должны использовать лямбду для опции :default, чтобы получить необработанное выражение nextval('global_seq') в базу данных.

Возможно, вы захотите удалить и старую последовательность, AFAIK, вам придется использовать 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.bigint и t.integer зависит от того, насколько большим вы хотите, чтобы ваш ПК был.

0 голосов
/ 13 октября 2018

Боюсь, что в миграциях 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 как «автономную» (оставаясь в БД, даже если таблица objects удалена).

...