2009-04-09 16 views

risposta

4

Non c'è un modo semplice per farlo. Puoi eseguire questa operazione eseguendo l'override del modulo ActiveRecord :: Timestamp o scrivendo la tua per eseguire la magia per te.

Here is come funziona la magia.

+2

FYI, il collegamento sopra riportato è per una versione precedente di Rails (2?). Se si utilizza Rails 3, vedere la risposta di NPatel. – Jared

+0

[Qui] (https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb) il modello dal ramo master rails – user980085

3

rapido brutto hack, elaborando dalla risposta di Milano Novota: aggiungere il seguente al environment.rb, sostituendo i valori delle CREATED_COL e UPDATED_COL costanti con i nomi delle colonne desiderati:


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

Grazie, questa è una buona soluzione. –

+0

Rails 3 ha reso questa soluzione obsoleta. Controlla quello di @NPatel per quello aggiornato. –

+0

Si prega di smettere di usare patch scimmia. – sickill

0

o si può solo rendere la vostra proprie colonne (DateTime) e imposta manualmente manualmente la colonna created_at quando crei e imposti la colonna updated_at quando aggiorni. Quello potrebbe essere più facile dell'hack sopra. Questo è quello che farò. Meglio ancora, aggiorna i binari per permetterci di cambiare questi nomi.

25

Questo può essere fatto semplicemente scrivendo i metodi del modulo ActiveRecord :: Timestamp. In realtà non sovrascrive l'intero modulo. Ho bisogno di raggiungere questo stesso obiettivo mentre sto lavorando con un database legacy. Sono su Rails 3 e ho iniziato a seguire una metodologia su come eseguire il patch di patch sul mio codice con funzionalità di scrittura over rails.

Prima creo il progetto di base con cui sto lavorando e creo un file chiamato quello negli inizializzatori. In questo caso ho creato active_record.rb. E all'interno del file ho inserito il codice per sovrascrivere due metodi che controllavano il timestamp. Di seguito è riportato l'esempio del mio codice:

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: Vorrei anche ricordare che questo tipo di scimmia patching per ottenere le cose al lavoro è visto di buon occhio e potrebbe rompersi per gli aggiornamenti in modo da essere attenti e essere pienamente consapevole di cosa vuoi fare.

Aggiornamenti:

  • cambiare i nomi delle colonne timestamp da simbolo a stringa per api change. Grazie a Techbrunch per aver portato questa modifica dell'API alla mia attenzione.
+0

Ottimo consiglio, ho salvato la giornata! –

+0

Si prega di smettere di usare patch scimmia. – sickill

+1

Questa risposta non è aggiornata, è necessario aggiornare il codice poiché 'timestamp_attributes_for_ {create, update}' è stato [modificato da simbolo a stringa] (https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257). – Techbrunch

22

Penso che il metodo di NPatel sia un approccio corretto, ma sta facendo troppo nel caso in cui sia necessario modificare #created_at su un singolo modello. Poiché il modulo Timestamp è incluso in ogni oggetto AR, è possibile sovrascriverlo per modello, non a livello globale. Di ':

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

Solo un FYI :)

+0

È ancora valido per Rails 5.1? Non sembra funzionare. – zmanw

+1

Questo metodo appartiene alla classe invece di un'istanza in Rails 5.1, quindi ora è 'private_class_method def self.timestamp_attributes_for_create' –

5

è possibile utilizzare la BeforeSave e metodi beforecreate di inviare il DateTime.now alle vostre colonne specificate.

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

Questo aggiornerà' created_column' ogni volta che si aggiorna il record –

+0

corretto. Grazie.. –

0

Un sol'n che non utilizza un patch di scimmia; utilizzare il blocco reversible durante la migrazione:

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 sintassi corretta per fare questo in rotaie 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 
Problemi correlati