Closed RonaldoSosa closed 4 years ago
Hola! Lo que sucede es que en realidad, your_column_name
en teoría debería ser el id
del otro modelo! Te mostraré un ejemplo.
class Author < ApplicationRecord
has_many :books
end
class Book < ApplicationRecord
belongs_to :author
end
Puedes ver en este caso que tus instancias de Author
deberían tener un atributo books
que corresponde a un arreglo de instancias de Book
. Por lo mismo, en la base de datos, la tabla para las instancias de Book
tendrá una columna que será author_id
, y corresponde al id
del usuario al que ese libro pertenece. Rails utiliza esta columna detrás de escena para hacer su magia y dejarte llamar author.books
directamente desde el código para ahorrarte tener que hacer las consultas tú mismo. En el fondo, las siguientes son equivalentes:
my_author = Author.find(params[:id])
# Rails haciendo magia
my_books = my_author.books
# Haciendo todo a mano
my_books = Book.where(author_id: my_author.id)
Por lo mismo, en el ejemplo que das, your_column_name
debería tener un nombre en particular, que corresponde al nombre del modelo relacionado en snake_case
seguido de _id
. Y dado que es un id
, tiene que ser un integer. Hay una forma más simple aún de agregar una referencia a una migración. Rails tiene un "alias" para la línea que escribiste, y se puede agregar una referencia en la migración con lo siguiente:
t.belongs_to :author
De esa forma, la migración entiende que los libros deben contener una referencia al id
del autor, y generan la columna automágicamente ✨
Entendido!Pero respecto a lo segundo que dijiste de editar la migración , ¿esto no es mala práctica?, recuerdo que en la ayudantía recomendaban usar comandos en lugar de editarlo a mano por así decirlo, partiendo de esto no sería equivalente a usar el comando: rails generate migration AddServiciosToCarretes services:references por ejemplo
Si y no. Déjame explicarte cómo funcionan las migraciones. Dado que tu aplicación está funcionando en un entorno de producción y en tu entorno de desarrollo, Rails debe tener una forma de saber qué cambios estructurales están hechos (a nivel de base de datos) en cada entorno y qué cambios no, para ejecutarlos. Por ejemplo, si tuvieras las migraciones A
y B
en producción y luego en una nueva branch generas la migración C
, cuando subas eso a producción, Rails sabrá que debe ejecutar solamente la migración C
y no A
ni B
(de eso se encarga Rails, tú no debes preocuparte, pero lo importante es que comprendas que solamente ejecuta las migraciones que no se han ejecutado antes). Por lo mismo, si en tu branch en vez de crear la migración C
editas la migración B
, al subir eso a producción Rails no alterará la base de datos, ya que recuerda que ya ha ejecutado A
y B
previamente (a pesar de que tú alteraste B
antes de volver a subir el código a producción). Eso significa que nunca debes tocar migraciones que ya hayas subido a GitHub (porque quizás otro compañero hizo pull del código que subiste y migró su base de datos con la migración C
, pero luego la cambiaste y ahora la base de datos de tu compañero estará "corrupta"). Este último caso no es tan terrible (porque puedes decirle a tu compañero que borre su base de datos y vuelva a ejecutar todas las migraciones, y ahí si se ejecutará la migración editada), pero se puede volver costumbre editar las migraciones ya existentes, y en el entorno de producción no se puede botar la base de datos y re-migrarla (por razones obvias). Por lo mismo, es una muy mala práctica editar migraciones ya existentes, y para tratar incluso de mantenerte alejado de los archivos de migraciones, Rails tiene sus comandos de línea para generar las migraciones por tí (no mucha gente entiende cómo funcionan las migraciones, y el resultado de editarlas a mano cuando no entiendes qué está sucediendo termina inevitablemente en una catástrofe). Sin embargo, si puedes editar a mano de manera segura tus archivos de migraciones, siempre y cuando te preocupes de las siguientes cosas:
Dicho esto, utilizar comandos es siempre seguro, ya que siempre crea una migración nueva, y eso no puede romper el esquema de la base de datos de otras máquinas. Por lo mismo, la decisión queda en tí, y depende de si prefieres tener control granular de qué está sucediendo (crear un archivo de migración "vacío" y editarlo a mano) o de si prefieres que ni siquiera exista la posibilidad de romper tu esquema de base de datos (utilizar comandos para crear la migración completa).
Yaaa!!!!Entonces si hago para hacer lo que tu me indicaste de t.belongs_to :author primero deberia hacer db:rollback hasta antes de la migración de los modelos y colocar esto , en cambio si uso lo de rails generate migration AddServiciosToCarretes services:references no seria necesario hacer todo esto aemás de que luego de hacer esto ya podría trabajar directamente con los archivos rb en la carpeta app/models como se nos indico en la ayudantía?
Depende! La migración de los modelos ya está en GitHub? Si está en GitHub, entonces no, deberías agregar una nueva migración en la que agregues el t.belongs_to :author
. Si la migración de modelos la hiciste en tu branch y aún no haces commit, entonces si, haces rollback hasta antes de esa migración, la editas y vuelves a migrar. Y si usas el comando, no sería necesario tocar el archivo de la migración. Ojo que en cualquiera de los dos casos deberás indicar la relación en tus modelos (los archivos dentro de app/models
), independiente de si editas la migración a mano o usando el comando.
Yaaaa!!Graciass!!!En mi caso ya había subido las migraciones a github así que use el comando , y solo para tenerlo claro luego de hacer el rails generate migration AddServiciosToCarretes services:references debo editar los modelos de app/models y recién una vez hecho eso aplicar el rails db:migrate o poría igual editarlos luego del db:migrate y se consideraria las relaciones que aplique?Pregunto esto porque no se si tiene el mismo efecto que cuando recién creo el modelo y lo aplico antes del db migrate , aunque en caso de ya haber hecho el db:migrate ya que aún no hago commit ni nada de eso lo podría solucionar con un db:roolback
Los modelos puedes editarlos cuando prefieras, ya que esas relaciones a Rails solamente le importan cuando corres tu código.
Ya me quedo claro ahora !!Gracias!!!!
Hola!Tengo una duda lo que pasa es que para la entrega anterior al momento de agregar las asociaciones a lo modelos no agregamos las referencias como se indico en la ayudantía sino que solo agregamos una variable del tipo string y trabajamos con eso , ahora para hacerlo correctamente estaba intentando remover esa columna y reemplazarla por otra en la cual se haga referencia a otro modelo , me guíe por esta página https://stackoverflow.com/questions/44948748/how-to-change-already-added-string-column-to-a-reference-in-rails , sin embargo aquí me indican que el comando para añadir la columna con referencias es el siguiente : add_column :table, :your_column_name, :integer, references: :your_parent_model Sin embargo , no entiendo la razón de agregar un :integer en este ejemplo o si es necesario agregarlo siempre.