重命名ActiveRecord / Rails的created_at,updated_at列

我想重命名timestamp.rb中定义的timestamp列。 timestamp.rb的方法可以被覆盖吗? 并且在应用程序中必须要使用具有覆盖方法的模块。

没有简单的方法可以做到这一点。 您可以通过覆盖ActiveRecord :: Timestamp模块,或者编写自己的模块来为您完成这项工作。

这就是神奇的作用。

这可以通过编写ActiveRecord :: Timestamp模块方法来完成。 实际上并没有覆盖整个模块。 我需要在使用遗留数据库时实现同样的目标。 我在轨道3上,我已经开始遵循一种方法,如何通过编写railsfunction来修补我的代码。

我首先创建我正在使用的基础项目,并在初始化程序中创建一个名为this的文件。 在这种情况下,我创建了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更改将时间戳列名称从符号更改为字符串。 感谢Techbrunch将此API更改引起我的注意。

我认为NPatel的方法是一种正确的方法,但如果您只需要在单个模型上更改#created_at,它就会做得太多。 由于Timestamp模块包含在每个AR对象中,因此您可以按模型覆盖它,而不是全局覆盖它。

<= Rails 5.0

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

Rails~> 5.1

  private_class_method def self.timestamp_attributes_for_create super << :registered_at end end 

您可以使用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 

快速丑陋的黑客,详细阐述了米兰诺瓦塔的回答:将以下内容附加到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 

在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 

或者您可以创建自己的列(DateTime),只需在创建时手动设置created_at列,并在更新时设置updated_at列。 这可能比上面的黑客更容易。 这就是我要做的。 更好的是,更新rails以允许我们更改这些名称。

一个不使用猴子补丁的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 

Rails更新anwser> = 5.1 。 我建议使用ApplicationRecord中默认可用的ApplicationRecord并定义以下内容:

 class ApplicationRecord < ActiveRecord::Base self.abstract_class = true class << self private def timestamp_attributes_for_create super << 'my_created_at_column' end def timestamp_attributes_for_update super << 'my_updated_at_column' end end end 

请注意 ,如果您不想为所有模型配置此块,也可以在特定型号上使用此块。

请注意 ,您应该使用字符串而不是符号。