2009-04-09 28 views

Respuesta

4

No hay una manera simple de hacerlo. Puede lograr esto anulando el módulo ActiveRecord :: Timestamp, o escribiendo uno propio para hacer la magia por usted.

Here is cómo funciona la magia.

+2

FYI, el enlace de arriba es para una versión anterior de Rails (2?). Si está utilizando Rails 3, vea la respuesta de NPatel. – Jared

+0

[Aquí] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb) el modelo de rails master branch – user980085

3

rápida truco feo, la elaboración de la respuesta de Milán Novota: agregar la siguiente environment.rb, en sustitución de los valores de las constantes CREATED_COL y UPDATED_COL con los nombres de las columnas deseadas:


module ActiveRecord 
    module Timestamp 
    CREATED_COL = 'created_at' 
    UPDATED_COL = 'updated_at' 
    private 
     def create_with_timestamps #:nodoc: 
     if record_timestamps 
      t = self.class.default_timezone == :utc ? Time.now.utc : Time.now 
      write_attribute(CREATED_COL, t) if respond_to?(CREATED_COL) && send(CREATED_COL).nil? 
      write_attribute(UPDATED_COL, t) if respond_to?(UPDATED_COL) && send(UPDATED_COL).nil? 
     end 
     create_without_timestamps 
     end 

     def update_with_timestamps(*args) #:nodoc: 
     if record_timestamps && (!partial_updates? || changed?) 
      t = self.class.default_timezone == :utc ? Time.now.utc : Time.now 
      write_attribute(UPDATED_COL, t) if respond_to?(UPDATED_COL) 
     end 
     update_without_timestamps(*args) 
     end 
    end 
end 
+0

Gracias, esta es una buena solución. –

+0

Rails 3 hizo obsoleta esta solución. Verifique el de @NPatel para obtener uno actualizado. –

+0

Deje de usar el parche de mono. – sickill

0

O simplemente podría hacer que su propias columnas (DateTime) y simplemente configure manualmente la columna created_at cuando cree y configure la columna updated_at cuando actualice. Eso podría ser más fácil que el truco anterior. Eso es lo que voy a hacer. Mejor aún, actualice los rieles para permitirnos cambiar estos nombres.

25

Esto puede hacerse simplemente escribiendo los métodos del módulo ActiveRecord :: Timestamp. En realidad, no sobrescribe todo el módulo. Necesito lograr este mismo objetivo ya que estoy trabajando con una base de datos heredada. Estoy en vías 3 y he comenzado a seguir una metodología de cómo parchear mi código con la funcionalidad de escribir sobre rieles.

Primero creo el proyecto base con el que estoy trabajando y creo un archivo llamado así en los inicializadores. En este caso, creé active_record.rb. Y dentro del archivo puse el código para anular dos métodos que controlaban la marca de tiempo. A continuación se muestra de mi código:

module ActiveRecord 
    module Timestamp  
     private 
     def timestamp_attributes_for_update #:nodoc: 
     ["updated_at", "updated_on", "modified_at"] 
     end 
     def timestamp_attributes_for_create #:nodoc: 
     ["created_at", "created_on"] 
     end  
    end 
    end 

NOTA: También me gustaría mencionar que este tipo de mono colocar un parche para que las cosas funcionen es mal visto y puede romperse en las actualizaciones de modo que tenga cuidado y ser plenamente consciente de qué es lo que quieres hacer.

actualizaciones:

  • cambiar los nombres de columna de marca de tiempo de símbolo a la cadena por api change. Gracias Techbrunch por llamarme la atención sobre este cambio en la API.
+0

¡Un gran consejo, me salvó el día! –

+0

Por favor deja de usar el parche de mono. – sickill

+1

Esta respuesta no está actualizada, deberá actualizar el código ya que 'timestamp_attributes_for_ {create, update}' ha sido [cambiado de símbolo a cadena] (https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257). – Techbrunch

22

Creo que el método de NPatel es un enfoque correcto, pero está haciendo demasiado en caso de que solo necesite cambiar #created_at en un solo modelo. Como el módulo Timestamp está incluido en todos los objetos AR, puede anularlo por modelo, no globalmente. Di:

class User < ActiveRecord::Base 
    ... 
private 
    def timestamp_attributes_for_create 
    super << :registered_at 
    end 
end 

Sólo un FYI :)

+0

¿Sigue siendo válido para Rails 5.1? No parece estar funcionando. – zmanw

+1

Este método pertenece a la clase en lugar de una instancia en Rails 5.1, por lo que ahora es 'private_class_method def self.timestamp_attributes_for_create' –

5

podría utilizar el beforesave y métodos beforecreate para publicar la DateTime.now a sus columnas especificadas.

class Sample < ActiveRecord::Base 
    before_create :set_time_stamps 
    before_save :set_time_stamps 

    private 
    def set_time_stamps 
    self.created_column = DateTime.now if self.new_record? 
    self.updated_column = DateTime.now 
    end 
end 
+0

Esto actualizará' created_column' cada vez que actualice el registro –

+0

Fixed. Gracias.. –

0

Una sol que no utiliza un parche de mono; utilizar el bloque reversible durante su migración:

class CreateTest < ActiveRecord::Migration 
    def change 

    create_table :test do |t| 
    end 

    # set the timestamp columns default to now() 
    reversible do |dir| 
     dir.up do 
     tables = [ 
      :test 
     ] 
     tables.each do |t| 
      execute <<-SQL 
      ALTER TABLE #{t.to_s} 
       add column created timestamp without time zone default now(); 
      SQL 
      execute <<-SQL 
      ALTER TABLE #{t.to_s} 
       add column updated timestamp without time zone default now(); 
      SQL 
     end 
     end 
     dir.down do 
     # no need to do anything, the rollback will drop the tables 
     end 
    end 

    end 
end 
0

La sintaxis correcta de hacer esto en los carriles 4.2

class User < ActiveRecord::Base 
... 

private 

    def timestamp_attributes_for_create 
     super << 'date_add' 
    end 

    def timestamp_attributes_for_update 
     super << 'date_update' 
    end 
end 
Cuestiones relacionadas