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_table
bloque. 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_timestamps
mé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 value
porque 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.now
es 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):
up
ydown
(y a veces unchange
método de instancia en 3.1). Desea que sus cambios entren en elup
método:Si está en 3.1, entonces también podría usar
change
(gracias Dave):Tal vez estás confundiendo
def change
,def change_table
ychange_table
.Consulte la guía de migración para más detalles.
fuente
change
ahora está el método, aunque en este caso, no es el problema :)change
vale 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
change
método en lugar dechange_table
:Si está utilizando una versión anterior, debe definir métodos
up
ydown
mé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.now
es lo que se debe usar si queremos que nuestro código obedezca a la zona horaria correcta.Time.zone.now
que 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::IrreversibleMigration
en adb:rollback
.Debe modificarse así para trabajar en ambas direcciones:
fuente
change_column_default
no es compatiblefrom
yto
en esa versión?), ¡Pero tomé esta idea y creéup/down
métodos en lugar de un solochange
mé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: true
después del:my_table
Hice 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_at
contienenull
valores'.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
ActiveRecord
comience 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_timestamps
desafortunadamente agrega lanull: false
restricció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_at
asNULL
yupdate_at
comoNULL
(hasta que se realice alguna actualización en la fila). Las nuevas filas tendráncreated_at
y se completaránupdated_at
como se esperaba.fuente
El problema con la mayoría de las respuestas aquí es que si usa
Time.zone.now
todos 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 end
fuente
Usar
Time.current
es 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_table
para 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