Как сделать столбец уникальным и проиндексировать его при переходе на Ruby on Rails?

366

Я хотел бы сделать столбец unique в миграции Ruby on Rails script. Каков наилучший способ сделать это? Также есть способ индексирования столбца в таблице?

Я хотел бы использовать столбцы unique в базе данных, а не просто использовать :validate_uniqueness_of.

Теги:

8 ответов

637
Лучший ответ

Короткий ответ:

add_index :table_name, :column_name, unique: true

Чтобы индексировать несколько столбцов вместе, вы передаете массив имен столбцов вместо имени одного столбца,

add_index :table_name, [:column_name_a, :column_name_b], unique: true

Для более тонкого управления существует метод < execute, который выполняет прямой SQL.

Что это!

Если вы делаете это как замену регулярной проверки старой модели, просто проверьте, как это работает. Я не уверен, что сообщение об ошибке пользователю будет таким же приятным. Вы всегда можете обойти оба.

  • 35
    +1 за предложение продолжать использовать validates_uniqueness_of. Обработка ошибок намного проще при использовании этого метода для стоимости одного индексированного запроса. Я бы сказал, что он делает оба
  • 1
    Я пытался, что это не похоже на работу! Я мог бы вставить две записи с column_name, которые я определил как уникальные! Я использую Rails 2.3.4 и MySql какие-либо идеи?
Показать ещё 9 комментариев
104

rails создает миграцию add_index_to_table_name column_name: uniq

или

rails создает миграцию add_column_name_to_table_name column_name: string: uniq: index

генерирует

class AddIndexToModerators < ActiveRecord::Migration
  def change
    add_column :moderators, :username, :string
    add_index :moderators, :username, unique: true
  end
end

Если вы добавляете индекс в существующий столбец, удалите или прокомментируйте строку add_column или установите флажок

add_column :moderators, :username, :string unless column_exists? :moderators, :username
  • 4
    Я проголосовал за это, потому что хотел форму командной строки. Но глупо, что он добавляет столбец, даже когда я указываю add_index... а не add_column...
  • 1
    Да, возможно в следующей версии.
31

Поскольку это еще не упоминалось, но отвечает на вопрос, который у меня был, когда я нашел эту страницу, вы также можете указать, что индекс должен быть уникальным при добавлении его через t.references или t.belongs_to:

create_table :accounts do |t|
  t.references :user, index: { unique: true } # or t.belongs_to

  # other columns...
end

(по крайней мере, Rails 4.2.7)

19

Если вы создаете новую таблицу, вы можете использовать встроенный ярлык:

  def change
    create_table :posts do |t|
      t.string :title, null: false, index: { unique: true }
      t.timestamps
    end
  end
11

Я использую Rails 5, и вышеупомянутые ответы отлично работают; здесь другой способ, который также работал у меня (имя таблицы :people, а имя столбца :email_address)

class AddIndexToEmailAddress < ActiveRecord::Migration[5.0]
  def change
    change_table :people do |t|
      t.index :email_address, unique: true
    end
  end
end
1
add_index :table_name, :column_name, unique: true

Чтобы индексировать несколько столбцов вместе, вы передаете массив имен столбцов вместо имени одного столбца.

0

Если вы пропустили добавление уникальности в столбец БД, просто добавьте эту проверку в модель, чтобы проверить, является ли поле уникальным:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name
end

см. здесь Выше только для целей тестирования, пожалуйста, добавьте индекс, изменив столбец БД, как предложено @Nate

пожалуйста, обратитесь к этому с индексом для получения дополнительной информации

  • 1
    Я бы не рекомендовал просто добавлять валидацию без соответствующего индекса. Лучший вариант - очистить все существующие дубликаты, а затем добавить индекс. В противном случае вы рискуете сделать недействительными существующие данные (что приведет к сбою любых обновлений в этих строках), и вы все равно можете получить дубликаты, если у вас есть какой-либо код, пропускающий проверки Rails. (например, при запуске update_all или прямой вставке SQL)
0

Возможно, вы захотите добавить имя для уникального ключа столько раз, что имя уникального_пользователя по умолчанию по рельсам может быть слишком длинным, для чего БД может вывести ошибку.

Чтобы добавить имя для вашего индекса, просто используйте параметр name:. Запрос миграции может выглядеть примерно так:

add_index :table_name, [:column_name_a, :column_name_b, ... :column_name_n], unique: true, name: 'my_custom_index_name'

Дополнительная информация - http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index

Ещё вопросы

Сообщество Overcoder
Наверх
Меню