Necesito agregar marcas de tiempo ( created_at& updated_at) a una tabla existente. Intenté el siguiente código pero no funcionó.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Necesito agregar marcas de tiempo ( created_at& updated_at) a una tabla existente. Intenté el siguiente código pero no funcionó.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
El asistente de marca de tiempo solo está disponible en el create_tablebloque. Puede agregar estas columnas especificando los tipos de columna manualmente:
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :users, :created_at, :datetime, null: false
add_column :users, :updated_at, :datetime, null: false
end
end
Si bien esto no tiene la misma sintaxis concisa que el add_timestampsmétodo que especificó anteriormente, Rails seguirá tratando estas columnas como columnas de marca de tiempo y actualizará los valores normalmente.
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime- un atajo para generar la migración anterior.PG::NotNullViolation: ERROR: column "created_at" contains null valueporque mi tabla ya contiene datos que violan la restricción no nula. ¿Alguna mejor manera de hacerlo que eliminar la contracción no nula al principio y luego agregarla?add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now.Time.zone.nowes solo un ejemplo, debe usar cualquier valor que tenga sentido para su lógica.Las migraciones son solo dos métodos de clase (o métodos de instancia en 3.1):
upydown(y a veces unchangemétodo de instancia en 3.1). Desea que sus cambios entren en elupmétodo:Si está en 3.1, entonces también podría usar
change(gracias Dave):Tal vez estás confundiendo
def change,def change_tableychange_table.Consulte la guía de migración para más detalles.
fuente
changeahora está el método, aunque en este caso, no es el problema :)changevale la pena mencionarlo, así que también lo agregaré.Su código original está muy cerca de la derecha, solo necesita usar un nombre de método diferente. Si está utilizando Rails 3.1 o posterior, debe definir un
changemétodo en lugar dechange_table:Si está utilizando una versión anterior, debe definir métodos
upydownmétodos en lugar dechange_table:fuente
La respuesta de @ user1899434 recogió el hecho de que una tabla "existente" aquí podría significar una tabla con registros ya en ella, registros que quizás no desee eliminar. Entonces, cuando agrega marcas de tiempo con nulo: falso, que es el valor predeterminado y, a menudo, deseable, todos los registros existentes no son válidos.
Pero creo que esa respuesta puede mejorarse, combinando los dos pasos en una migración, y usando el método más semántico add_timestamps:
Podría sustituir alguna otra marca de tiempo
DateTime.now, como si quisiera crear / actualizar registros preexistentes al comienzo de los tiempos.fuente
Time.zone.nowes lo que se debe usar si queremos que nuestro código obedezca a la zona horaria correcta.Time.zone.nowque devolverá la instancia de Time que se crea cuando se ejecuta la migración y solo usará ese tiempo como predeterminado. Los nuevos objetos no obtendrán una nueva instancia de Time.Las transformaciones disponibles son
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
fuente
La respuesta de Nick Davies es la más completa en términos de agregar columnas de marca de tiempo a una tabla con datos existentes. Su único inconveniente es que aumentará
ActiveRecord::IrreversibleMigrationen adb:rollback.Debe modificarse así para trabajar en ambas direcciones:
fuente
change_column_defaultno es compatiblefromytoen esa versión?), ¡Pero tomé esta idea y creéup/downmétodos en lugar de un solochangemétodo y funcionó de maravilla!fuente
no estoy seguro de cuándo se introdujo exactamente esto, pero en rails 5.2.1 puede hacer esto:
para obtener más información, consulte " uso del método de cambio " en los documentos de migraciones de registros activos.
fuente
, null: truedespués del:my_tableHice una función simple que puede llamar para agregar a cada tabla (suponiendo que tenga una base de datos existente) los campos created_at y updated_at :
fuente
Agrega columnas de marcas de tiempo (created_at y updated_at) a table_name. Las opciones adicionales (como null: false) se envían a #add_column.
fuente
Las respuestas anteriores parecen correctas, sin embargo, tuve problemas si mi tabla ya tiene entradas.
Obtendría 'ERROR: la columna
created_atcontienenullvalores'.Para arreglarlo, usé:
Luego usé la gema migración_datos para agregar el tiempo para los proyectos actuales en la migración, tales como:
Luego, todos los proyectos creados después de esta migración se actualizarán correctamente. Asegúrese de que el servidor también se reinicie para que Rails
ActiveRecordcomience a rastrear las marcas de tiempo en el registro.fuente
Muchas respuestas aquí, pero también publicaré las mías porque ninguna de las anteriores realmente funcionó para mí :)
Como algunos han notado,
#add_timestampsdesafortunadamente agrega lanull: falserestricción, lo que hará que las filas antiguas no sean válidas porque no tienen estos valores rellenados. La mayoría de las respuestas aquí sugieren que establezcamos un valor predeterminado (Time.zone.now), pero no me gustaría hacerlo porque estas marcas de tiempo predeterminadas para datos antiguos no serán correctas. No veo el valor en agregar datos incorrectos a la tabla.Entonces mi migración fue simplemente:
No
null: false, no hay otras restricciones. Las filas antiguas continuarán siendo válidas concreated_atasNULLyupdate_atcomoNULL(hasta que se realice alguna actualización en la fila). Las nuevas filas tendráncreated_aty se completaránupdated_atcomo se esperaba.fuente
El problema con la mayoría de las respuestas aquí es que si usa
Time.zone.nowtodos los registros de manera predeterminada , el tiempo de ejecución de la migración será el tiempo predeterminado, lo que probablemente no sea lo que desea. En los rieles 5 puedes usarlosnow(). Esto establecerá las marcas de tiempo para los registros existentes como la hora en que se ejecutó la migración y como la hora de inicio de la transacción de confirmación para los registros recién insertados.class AddTimestampsToUsers < ActiveRecord::Migration def change add_timestamps :users, default: -> { 'now()' }, null: false end endfuente
Usar
Time.currentes un buen estilo https://github.com/rubocop-hq/rails-style-guide#timenowo
fuente
Este es uno simple para agregar marca de tiempo en la tabla existente.
fuente
Para aquellos que no usan Rails pero sí usan activerecord, lo siguiente también agrega una columna a un modelo existente, por ejemplo, para un campo entero.
fuente
Es
change, nochange_tablepara rieles 4.2:fuente
Esto parece una solución limpia en Rails 5.0.7 (descubrió el método change_column_null):
fuente
Estoy en rails 5.0 y ninguna de estas opciones funcionó.
Lo único que funcionó fue usar el tipo to be: timestamp y not: datetime
fuente
Personalmente utilicé lo siguiente y actualizó todos los registros anteriores con la hora / fecha actual:
fuente
Me encontré con el mismo problema en Rails 5 tratando de usar
Pude agregar las columnas de marca de tiempo manualmente con lo siguiente:
fuente