23

que tenía una migración add_column que funcionaría bien. Sin embargo, después de ejecutarlo y encender una consola, encontraría las columnas first_name y last_name completamente vacías. Intenté usar save! en su lugar y tuvo el mismo efecto: no se informaron errores. Aquí está el original:Rails 3.1: No se puede escribir en la columna en la misma migración que se suma que

class UserAddFirstNameAndLastName < ActiveRecord::Migration 
    def change 
    # add column first name, last name string 
    add_column :users, :first_name, :string 
    add_column :users, :last_name, :string 

    User.all.each do |u| 
     u.first_name = 'first name' 
     u.last_name = 'last name' 
     u.save 
    end 
    end 
end 

también pensé que esto podría haber algún problema de la carga de clases, por lo que inserta la línea User para obligar a la clase de usuario para recargar antes del bucle. No dados.

Cuando dividir este en dos migraciones, se logró el efecto deseado. ¿Alguien tiene una explicación para esto? Juro que incluso hice esto en el mismo proyecto con migraciones pasadas.

Otras notas: Idear para el motor de usuario, añaden las nuevas columnas a attr_accessible en la clase de usuario antes de ejecutar la migración.

+1

mu es demasiado corto tiene una respuesta fantástica para explicar lo que está pasando y qué hacer, pero también me gustaría recomendar la división de estos dos en diferentes migraciones. Crea columnas en una, rellena en otra. Esto evita el problema que está viendo y hace que las reversiones sean menos propensas a errores. –

Respuesta

37

va a cargar la clase de usuarios en algún lugar antes de la migración se ejecuta de manera User es un poco confundido acerca de su propia estructura. La solución es llamar reset_column_information después de la adición de su columna:

Restablece toda la información acerca de las columnas en caché, lo que hará que se pueden recargar en la siguiente solicitud.

El patrón de uso más común para este método es, probablemente, en una migración, cuando justo después de la creación de una tabla que desea rellenarlo con algunos valores por defecto

La sección Using Models in Your Migrations del Migrations Guide podría ser digno de una mirada también.

intenta reanudar y el uso de una migración de esta manera:

def change 
    # add column first name, last name string 
    add_column :users, :first_name, :string 
    add_column :users, :last_name, :string 

    User.reset_column_information 

    User.all.each do |u| 
    u.first_name = 'first name' 
    u.last_name = 'last name' 
    u.save 
    end 
end 

he comprobado esto con tres migraciones como este:

# 1: Don't touch Model before the new columns. 
def change 
    add_column :models, :some_column, :string 
    Model.all.each { |m| m.some_column = 'pancakes'; m.save } 
end 

# 2: Pull in Model before adding the new columns. 
def change 
    puts Model.all.count 
    add_column :models, :some_column, :string 
    Model.all.each { |m| m.some_column = 'pancakes'; m.save } 
end 

# 3: Pull in Model before adding the new columns but use reset_column_information 
def change 
    puts Model.all.count 
    add_column :models, :some_column, :string 
    Model.reset_column_information 
    Model.all.each { |m| m.some_column = 'pancakes'; m.save } 
end 

El primero funciona bien, el segundo añade some_column pero lo deja con valores NULL, el tercero también funciona.

supongo que algo en su inicialización de la aplicación (posiblemente de Idear) está causando usuario y su esquema se va a cargar, a continuación, agregar una columna. Pero, al parecer, el usuario solo sabe en parte sobre la nueva columna ya que la llamada u.first_name funciona, pero hay algo almacenado en caché dentro de Usuario para evitar que el atributo se escriba en la base de datos.

+0

Confirmó que este era el problema con una advertencia. Acabo de usar su primer y tercer ejemplo juntos en una migración. El primero no se guardó en la base de datos. Completé nuestra carpeta DB y tenía razón antes. Tengo migraciones antiguas con salvaciones como esta. Algo que agregamos a nuestro proyecto está causando que los modelos se precarguen antes de las migraciones ... Sospecho que podría ser la gema 'active_reload'. Todavía no nos hemos actualizado a Rails 3.2 pero noto que esta es una característica estándar ahora. Espero confirmar/refutar esto con pruebas si tengo tiempo. –

+0

@Eric: Algo en su inicialización está precargando su clase de modelo. (1) funcionó para mí porque nada en mi inicialización está precargando nada; the 'puts Model.all.count' en (2) y (3) es solo una manera fácil de simular la precarga que está ocurriendo en su entorno. 'active_reload' suena como un posible sospechoso. Agregar el 'reset_column_information' si modifica y usa un modelo en una migración es probablemente un buen hábito para entrar. –

+0

Esto no funciona en Rails 4. –

Cuestiones relacionadas