Carriles: agregar un índice después de agregar una columna

119

Supongamos que creé una tabla tableen una aplicación Rails. Algún tiempo después, agrego una columna que se ejecuta:

rails generate migration AddUser_idColumnToTable user_id:string. 

Entonces me doy cuenta de que necesito agregar user_idcomo índice. Conozco el add_indexmétodo, pero ¿dónde debería llamarse este método? ¿Se supone que debo ejecutar una migración (en caso afirmativo, cuál?), Y luego agregar manualmente este método?

usuario1611830
fuente

Respuestas:

235

Puede ejecutar otra migración, solo para el índice:

class AddIndexToTable < ActiveRecord::Migration
  def change
    add_index :table, :user_id
  end
end
Jaap Haagmans
fuente
4
Así que simplemente ejecuto en mi consola: ¿los rieles generan la migración AddIndexToTable?
user1611830
3
Sí, puede hacerlo, pero tendrá que editar esa migración posteriormente para reflejar el código anterior.
Jaap Haagmans
¿Se supone que la tabla es plural?
tumba
1
@tomb Usé el ejemplo de la pregunta original. :tablees el nombre real de la tabla, por lo que, en el caso de una userstabla, lo sustituiría :userspor :table.
Jaap Haagmans
65

Si necesita crear una user_id, sería razonable suponer que está haciendo referencia a una tabla de usuarios. En cuyo caso la migración será:

rails generate migration AddUserRefToProducts user:references

Este comando generará la siguiente migración:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :user, :product, index: true
  end
end

Después de ejecutar rake db:migratetanto una user_idcolumna como un índice, se agregarán a la productstabla.

En caso de que solo necesite agregar un índice a una columna existente, por ejemplo, namede una usertabla, la siguiente técnica puede ser útil:

rails generate migration AddIndexToUsers name:string:index generará la siguiente migración:

class AddIndexToUsers < ActiveRecord::Migration
  def change
    add_column :users, :name, :string
    add_index :users, :name
  end
end

Elimina la add_columnlínea y ejecuta la migración.

En el caso descrito, podría haber emitido un rails generate migration AddIndexIdToTable index_id:integer:indexcomando y luego eliminar la add_columnlínea de la migración generada. Pero prefiero recomendar deshacer la migración inicial y agregar una referencia en su lugar:

rails generate migration RemoveUserIdFromProducts user_id:integer
rails generate migration AddUserRefToProducts user:references
Vadym Tyemirov
fuente
Gracias Vadym por la respuesta completa. Una última pregunta: ¿por qué recomendaría deshacer la migración inicial? ¿Hay algún problema de rendimiento relacionado con la adición de índice más adelante?
Flavio Wuensche
2
Para @fwuensche: no hay ninguna penalización de rendimiento por agregar índice más adelante. Sin embargo, la lógica del dominio será menos clara. Por ejemplo, en caso de que decida romper / abstraer / etc la asociación más adelante, tendrá que lidiar con dos migraciones separadas, que realmente deberían haber sido una sola ...
Vadym Tyemirov
6
ADVERTENCIA: Tenga en cuenta que index: true solo funciona en una migración create_table. La migración se ejecutará, pero no se creará ningún índice. Ver makandracards.com/makandra/…
rmcsharry
9

Agregue en la migración generada después de crear la columna lo siguiente (ejemplo)

add_index :photographers, :email, :unique => true
rdeandrade
fuente
quieres decir algo como esto: def self.up add_column ... end add_index ...?
user1611830
5

Para referencias puede llamar

rails generate migration AddUserIdColumnToTable user:references

Si en el futuro necesita agregar un índice general, puede iniciar este

rails g migration AddOrdinationNumberToTable ordination_number:integer:index

Generar codigo:

class AddOrdinationNumberToTable < ActiveRecord::Migration
  def change
   add_column :tables, :ordination_number, :integer
   add_index :tables, :ordination_number, unique: true
  end
end
Mauro
fuente
0

Puede usar esto, solo piense que Job es el nombre del modelo al que está agregando index cader_id :

class AddCaderIdToJob < ActiveRecord::Migration[5.2]
  def change
    change_table :jobs do |t|
      t.integer :cader_id
      t.index :cader_id
    end
  end
end
vidur punj
fuente