Как мне обрабатывать слишком длинные имена индексов при переносе Ruby on Rails ActiveRecord?

Я пытаюсь добавить уникальный индекс, который создается из внешних ключей четырех связанных таблиц:

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"],
  :unique => true

Ограничение базы данных для имени индекса приводит к сбою миграции. Вот сообщение об ошибке:

Имя индекса 'index_studies_on_user_id_and_university_id_and_subject_name_id_and_subject_type_id' в таблице 'Studies' слишком длинное; ограничение составляет 64 символа

Как я могу справиться с этим? Могу ли я указать другое имя индекса?

Ответ 1

Укажите параметр :name для add_index, например:

add_index :studies,
  ["user_id", "university_id", "subject_name_id", "subject_type_id"], 
  :unique => true,
  :name => 'my_index'

При использовании опции :index в references в блоке create_table в качестве значения берется тот же хеш опций, что и в add_index:

t.references :long_name, index: { name: :my_index }

Ответ 2

Вы также можете изменить имя индекса в определениях столбцов в блоке create_table (например, из генератора миграции).

create_table :studies do |t|
  t.references :user, index: {:name => "index_my_shorter_name"}
end

Ответ 3

В PostgreSQL предел по умолчанию - 63 символа. Поскольку имена индексов должны быть уникальными, приятно иметь небольшое соглашение. Я использую (я объяснил пример, чтобы объяснить более сложные конструкции):

def change
  add_index :studies, [:professor_id, :user_id], name: :idx_study_professor_user
end

Нормальный индекс был бы:

:index_studies_on_professor_id_and_user_id

Логика будет:

  • index становится idx
  • Имя отдельной таблицы
  • Не присоединяется к словам
  • Нет _id
  • Алфавитный порядок

Что обычно выполняет задание.

Ответ 4

Вы также можете сделать

t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')

как в API Ruby on Rails.

Ответ 5

Как и в предыдущем ответе: просто используйте ключ "name" с вашей обычной линией add_index:

def change
  add_index :studies, :user_id, name: 'my_index'
end

Ответ 6

У меня была эта проблема, но с функцией timestamps. Он автоматически генерировал индекс для updated_at, который превысил ограничение в 63 символа:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps
  end
end

Имя индекса 'index_toooooooooo_loooooooooooooooooooooooooooooong_on_updated_at' в таблице 'toooooooooo_loooooooooooooooooooooooooooooooong' слишком длинное; ограничение составляет 63 символа

Я пытался использовать timestamps для указания имени индекса:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.timestamps index: { name: 'too_loooooooooooooooooooooooooooooong_updated_at' }
  end
end

Тем не менее, он пытается применить имя индекса к полям updated_at и created_at:

Имя индекса 'too_long_updated_at' в таблице 'toooooooooo_loooooooooooooooooooooooooooooong' уже существует

Наконец, я отказался от timestamps и просто создал метки времени:

def change
  create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
    t.datetime :updated_at, index: { name: 'too_long_on_updated_at' }
    t.datetime :created_at, index: { name: 'too_long_on_created_at' }
  end
end

Это работает, но я бы хотел услышать, если это возможно с помощью метода timestamps!