generar modelo usando user: references vs user_id: integer

176

Estoy confundido sobre cómo generar un modelo que pertenece a otro modelo. Mi libro usa esta sintaxis para asociar Micropost con el usuario:

rails generate model Micropost user_id:integer

pero http://guides.rubyonrails.org/ dice hacerlo así:

rails generate model Micropost user:references

Las migraciones generadas por estos 2 son diferentes. Además, para el primero, ¿cómo sabe Rails que se user_idtrata de una referencia de clave externa user? ¡Gracias!

stackOverlord
fuente

Respuestas:

190

Ambos generarán las mismas columnas cuando ejecutes la migración. En la consola de rails, puede ver que este es el caso:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

El segundo comando agrega una belongs_to :userrelación en su modelo de Micropost mientras que el primero no. Cuando se especifica esta relación, ActiveRecord asumirá que la clave externa se mantiene en la user_idcolumna y usará un modelo nombrado Userpara crear una instancia del usuario específico.

El segundo comando también agrega un índice en la nueva user_idcolumna.

Jon M.
fuente
1
¿Es posible generar un modelo con referencias de dos tablas
Praveenkumar
Tenga en cuenta que no agrega una asociación has_many en el otro modelo (usuario), que también puede agregar.
Sv1
45

¿Cómo sabe Rails que se user_idtrata de una referencia de clave externa user?

Rails en sí mismo no sabe que se user_idtrata de una referencia de clave externa user. En el primer comando rails generate model Micropost user_id:integersolo agrega una columna, user_idsin embargo, rails no conoce el uso de la columna. Necesita poner manualmente la línea en el Micropostmodelo

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

las palabras clave belongs_toy has_manydeterminar la relación entre estos modelos y declarar user_idcomo una clave externa para Usermodelar.

El comando posterior rails generate model Micropost user:referencesagrega la línea belongs_to :useren el Micropostmodelo y por la presente se declara como una clave foránea.

Para su información,
declarar las claves foráneas utilizando el método anterior solo permite que los Rails sepan sobre la relación que tienen los modelos / tablas. La base de datos es desconocida sobre la relación. Por lo tanto, cuando genera los diagramas EER utilizando un software como el MySql Workbenchque encuentra, no hay hilos de relación entre los modelos. Como en la siguiente foto ingrese la descripción de la imagen aquí

Sin embargo, si utiliza el método posterior, encontrará que su archivo de migración se ve así:

def change
    create_table :microposts do |t|
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :microposts, :users

Ahora la clave externa se establece en el nivel de la base de datos. y puedes generar EERdiagramas adecuados . ingrese la descripción de la imagen aquí

ilusionista
fuente
1
Parece que el último generador de Rails reemplazó la add_foreign_keyacción con una opción foreign_key: truea la t.referenceslínea, lo que implica index: true. Así es ahora t.references :user, foreign_key: true. Actualmente no hay documentación para la foreign_keyopción disponible, por lo que esta es solo mi suposición.
Franklin Yu
Oh, la add_referenceacción tiene una :foreign_keyopción que agrega una restricción de clave externa apropiada . Supongo que esta opción haría lo mismo al crear la tabla.
Franklin Yu
¿Cómo exportas tu ruby ​​db a workbench? ¿podría responder esto aquí: stackoverflow.com/questions/42982921/…
Krawalla
¿Tener add_foreign_key :microposts, :users alguna diferencia para Rails?
Linus
17

Para el primero, convención sobre configuración. Los rieles predeterminados cuando hace referencia a otra tabla con

 belongs_to :something

es buscar something_id.

references, o en belongs_torealidad es una forma más nueva de escribir el primero con pocas peculiaridades.

Es importante recordar que no creará claves foráneas para usted. Para hacer eso, debe configurarlo explícitamente usando:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true

o (tenga en cuenta el plural):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Krule
fuente
1
¿Puede explicar a qué se refiere al decir que las referencias no crearán claves foráneas para usted? ¿En qué se diferencia del primer comando que usa user_id: integer directamente?
shailesh
No lo es, excepto en el caso de que esté utilizando la :polymorphicopción (que en mi humilde opinión, en la mayoría de los casos, no es una buena idea). Si desea utilizar claves foráneas en ActiveRecord, use extranjero .
Krule
1
@Krule Now add_foreign_keyha llegado a ActiveRecord.
Franklin Yu