Migraciones de Rails 3: ¿Agregar columna de referencia?

162

Si creo una nueva migración de rails 3 con (por ejemplo)

rails g migration tester title:tester user:references

, todo funciona bien ... sin embargo, si agrego una columna con algo similar a:

rails g migration add_user_to_tester user:references

el campo de referencia no se reconoce. En resumen, la pregunta es: ¿cómo agrego una columna de referencia a una migración de rieles desde la línea de comandos?

Plancton
fuente

Respuestas:

205

Si está utilizando Rails 4.x ahora puede generar migraciones con referencias, como esta:

rails generate migration AddUserRefToProducts user:references

como puedes ver en las guías de rieles

Paulo Fidalgo
fuente
1
Consulte la sección 2.1 de edgeguides.rubyonrails.org/active_record_migrations.html, por ejemplo.
B Seven
2
¿Cómo se especifica un nombre de columna para la clave externa en lugar del nombre generado automáticamente?
j será el
@jwill puede usar polymorphic: user: references {polymorphic}.
Paulo Fidalgo
@PauloFidalgo ¿Puedes explicar un poco sobre cómo hacer eso? puede haber alguna guía de enlaces? (hablando de polimórficos)
Anwar
@Anwar: aquí están los documentos api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/…
Paulo Fidalgo
186

EDITAR : Esta es una respuesta obsoleta y no debe aplicarse a Rails 4.x +

No necesita agregar referencias cuando puede usar una identificación entera para su clase referenciada.

Diría que la ventaja de usar referencias en lugar de un entero simple es que el modelo estará predefinido con belong_to y dado que el modelo ya está creado y no se verá afectado cuando migre algo existente, el propósito se pierde.

Entonces me gustaría hacer esto en su lugar:

rails g migration add_user_id_to_tester user_id:integer

Y luego agregue manualmente belong_to: usuario en el modelo Tester

DanneManne
fuente
9
Pero eso no creará las restricciones de clave externa apropiadas en las bases de datos que lo admiten, ¿verdad?
abahgat
19
No, afaik Rails nunca crea restricciones de clave externa en la base de datos a menos que agregue complementos para hacerlo por usted.
DanneManne
solo estudiando esta publicación, por favor, ¿cómo agrego la referencia después de todo?
El niño
13
recuerde agregar el índice con user: integer: index
rickypai
3
La respuesta está fechada, consulte la respuesta de @ Paulo para los rieles modernos.
OneHoopyFrood
102

Tenga en cuenta que probablemente también necesitará un índice en esa columna.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end
Eugene
fuente
1
¿Por qué? ¿Es esto cierto para la mayoría de las relaciones pertenecientes a?
ahnbizcad
De hecho, es por razones de rendimiento y es útil si tiene un has_many / has_one en el otro lado de esa relación pertenece a. Si está absolutamente seguro de que no lo hará user.testers, puede omitir el índice.
Eugene
1
El rails g migration ...generado add_reference :installs, :device, index: trueque también crea el índice.
B Seven
49

Con los dos pasos anteriores indicados anteriormente, todavía te falta la restricción de clave externa. Esto debería funcionar:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end
Martin Cabrera Diaubalick
fuente
Esta es la única respuesta real aquí. La clave externa es la parte más crítica aquí
usuario2490003
esto debe marcarse como la respuesta correcta ya que las preguntas piden rieles 3
Carlos Roque
35

Usted puede utilizar referencias en una migración cambio. Este es el código válido de Rails 3.2.13:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table

gl03
fuente
1
cambiar y bajar métodos? ¿No son métodos de subida y bajada en su lugar?
MaicolBen
@MaicolBen sí, y también puedes dejar el método inactivo.
Choza8
@MaicolBen Sin el downmétodo, obtuve ActiveRecord::IrreversibleMigrational retroceder usando Rails 3.2. También he tenido que cambiar changea up.
Andrew Grimm
27

La ejecución rails g migration AddUserRefToSponsors user:referencesgenerará la siguiente migración:

def change
  add_reference :sponsors, :user, index: true
end
Wirwing
fuente
¿Para qué versión de Rails es esto?
Andrew Grimm
8

Al agregar una columna, debe hacer que esa columna sea un número entero y, si es posible, cumplir con las convenciones de rieles. Entonces, para su caso, supongo que ya tiene un Tester y modelos de usuario, y testers y tablas de usuarios.

Para agregar la clave externa, debe crear una columna entera con el nombre user_id (convención):

add_column :tester, :user_id, :integer

A continuación, agregue un pertenece_ al modelo de prueba:

class Tester < ActiveRecord::Base
  belongs_to :user
end

Y es posible que también desee agregar un índice para la clave externa (esto es algo que las referencias ya hacen por usted):

add_index :tester, :user_id
Zamith
fuente
8

Eso hará el truco:

rails g migration add_user_to_tester user_id:integer:index
masterweily
fuente
Me gusta que esto también agregue el índice que probablemente querrás.
bheeshmar
3

Puede agregar referencias a su modelo a través de la línea de comandos de la siguiente manera:

rails g migration add_column_to_tester user_id:integer

Esto generará un archivo de migración como:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Esto funciona bien cada vez que lo uso ...

Neha
fuente
3

Para rieles 4

El generador acepta el tipo de columna como referencias (también disponible como belongs_to).

Esta migración creará una user_idcolumna y un índice apropiado:

$ rails g migration AddUserRefToProducts user:references 

genera:

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

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

Para rieles 3

Helper se llama referencias (también disponible como belongs_to).

Esta migración creará una category_idcolumna del tipo apropiado. Tenga en cuenta que pasa el nombre del modelo, no el nombre de la columna. Active Record agrega el _idpara usted.

change_table :products do |t|
  t.references :category
end

Si tiene belongs_toasociaciones polimórficas , las referencias agregarán las dos columnas requeridas:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Agregará una columna attach_id y una attachment_typecolumna de cadena con un valor predeterminado de Photo.

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

shilovk
fuente