Jak zrobić kolumnę unikalną i indeksować ją w Ruby on Rails migration?

Chciałbym utworzyć kolumnę unique w Ruby on Rails migration script. Jak najlepiej to zrobić? Czy istnieje również sposób na indeksowanie kolumny w tabeli?

Chciałbym wymuszać unique kolumny w bazie danych, a nie tylko używać :validate_uniqueness_of.

Author: Peter Mortensen, 2009-09-20

7 answers

Krótka odpowiedź:

add_index :table_name, :column_name, unique: true

Aby indeksować wiele kolumn razem, przekazujesz tablicę nazw kolumn zamiast nazwy pojedynczej kolumny,

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

Dla drobniejszych kontroli istnieje metoda" execute", która wykonuje prosty SQL.

To jest to!

Jeśli robisz to jako zamiennik dla zwykłych walidacji starego modelu, po prostu sprawdź, jak to działa. Nie jestem pewien, czy zgłaszanie błędów do użytkownika będzie tak miłe. Zawsze możesz zrobić jedno i drugie.

 595
Author: ndp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 14:24:28

Rails generuje migrację add_index_to_table_name column_name: uniq

Lub

Rails generuje migrację add_column_name_to_table_name column_name: string: uniq: index

Generuje

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

Jeśli dodajesz indeks do istniejącej kolumny, Usuń lub skomentuj linię add_column lub włóż czek

add_column :moderators, :username, :string unless column_exists? :moderators, :username
 103
Author: d.danailov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 16:04:06

Ponieważ nie zostało to jeszcze wspomniane, ale odpowiada na pytanie, które miałem, gdy znalazłem tę stronę, możesz również określić, że indeks powinien być unikalny podczas dodawania go przez t.references lub t.belongs_to:

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

  # other columns...
end

(od co najmniej Rails 4.2.7)

 25
Author: Steve Grossi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-10 17:30:42

Jeśli tworzysz nową tabelę, możesz użyć skrótu w wierszu:

  def change
    create_table :posts do |t|
      t.string :title, null: false, index: { unique: true }
      t.timestamps
    end
  end
 13
Author: Pioz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-07 15:12:54

Używam Rails 5 i powyższe odpowiedzi działają świetnie; oto inny sposób, który również działał dla mnie (nazwa tabeli to :people, a nazwa kolumny to :email_address)

class AddIndexToEmailAddress < ActiveRecord::Migration[5.0]
  def change
    change_table :people do |t|
      t.index :email_address, unique: true
    end
  end
end
 10
Author: Nicholas Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-10 16:52:42
add_index :table_name, :column_name, unique: true

Aby indeksować wiele kolumn razem, przekazujesz tablicę nazw kolumn zamiast nazwy pojedynczej kolumny.

 1
Author: murali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-29 08:55:15

Możesz dodać nazwę dla unikalnego klucza, ponieważ domyślna nazwa unique_key przez rails może być zbyt długa, przez co DB może wyrzucić błąd.

Aby dodać nazwę dla indeksu wystarczy użyć opcji name:. Zapytanie o migrację może wyglądać mniej więcej tak -

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

Więcej informacji - http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index

 0
Author: Swaps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 11:39:56