2009-04-09 99 views

回答

4

沒有簡單的方法來做到這一點。你可以通過覆蓋ActiveRecord :: Timestamp模塊來完成這個任務,或者通過編寫自己的模塊來爲你實現魔法。

Here is魔法如何運作。

+2

僅供參考,上面的鏈接是針對舊版Rails(2?)。如果您使用的是Rails 3,請參閱NPatel的答案。 – Jared 2011-09-12 22:26:03

+0

[這裏](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb)從軌道模型掌握分支 – user980085 2015-07-04 14:30:52

3

快速醜陋的黑客攻擊,從米蘭Novota的回答闡述:追加以下的environment.rb來,與所需的列名替換CREATED_COL和UPDATED_COL常量的值:


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

謝謝,這是一個很好的解決方案。 – 2009-04-10 15:20:48

+0

Rails 3使這個解決方案過時了。從@NPatel中檢查一個更新的。 – 2011-04-11 16:12:57

+0

請停止使用猴子補丁。 – sickill 2015-06-05 08:36:12

0

或者你可以讓你的自己的列(DateTime),並且當您更新時創建並設置updated_at列時,只需手動設置created_at列。這可能比上面的黑客更容易。這就是我要做的。更好的是,更新rails以允許我們更改這些名稱。

25

這可以通過編寫ActiveRecord :: Timestamp模塊方法完成。實際上並未覆蓋整個模塊。我需要完成與使用舊數據庫相同的目標。我在rails 3上,我開始遵循如何通過寫入rails功能來修補我的代碼的方法。

我首先創建了我正在使用的基礎項目,並在初始化程序中創建了一個名爲該項目的文件。在這種情況下,我創建了active_record.rb。在文件中,我把代碼覆蓋了兩個控制時間戳的方法。下面是我的代碼示例:

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 

注:我也想提一提,這種猴子的修補來把事情的工作是不可取的,並在升級可能會中斷,所以要小心,並充分意識到你想要做什麼。

更新:

  • 變化從符號時間戳列名於每api change字符串。感謝Techbrunch將此API改變爲我的注意。
22

我認爲NPatel的方法是一種正確的方法,但是如果您只需要在單個模型上更改#created_at,則做得太多了。由於Timestamp模塊包含在每個AR對象中,因此可以在每個模型中覆蓋它,而不是全局。你說:

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

只是一個僅供參考:)

5

您可以使用beforesave和beforecreate方法的DateTime.now張貼到您指定的列。

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

不使用猴子補丁的sol'n;在遷移期間使用reversible塊:

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

在rails 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