重命名ActiveRecord/Rails的created_at、updated_at列

时间:2022-01-29 12:13:44

I want to rename the timestamp columns defined in timestamp.rb . Can the methods of timestamp.rb be overwritten? And what has to be done in the application that the module with the overwritten methods is used.

我想重命名时间戳中定义的时间戳列。rb。时间戳的方法。rb被覆盖?在应用程序中需要做的是使用覆盖方法的模块。

8 个解决方案

#1


4  

There is no simple way to do that. You can accomplish this either by overriding the ActiveRecord::Timestamp module, or by writing your own one to do the magic for you.

没有简单的方法可以做到这一点。您可以通过覆盖ActiveRecord::Timestamp模块或者编写自己的模块来实现这一点。

Here is how the magic works.

这就是魔术的原理。

#2


25  

This can be done via just over writing the ActiveRecord::Timestamp module methods. Not actually overwriting the entire module. I need to to accomplish this same goal as I am working with a legacy database. I am on rails 3 and I have started following a methodology of how to monkey patch my code with over writing rails functionality.

这可以通过编写ActiveRecord::Timestamp模块方法来完成。不是覆盖整个模块。我需要在使用遗留数据库时完成相同的目标。我已经在rails 3上了,并且我已经开始使用一种方法,即如何通过编写rails功能来修改代码。

I first create the base project that I am working with and create a file called that in the initializers. In this case I created active_record.rb. And within the file I put code to override two methods that controlled the timestamp. Below is the sample of my code:

我首先创建我正在处理的基础项目,并在初始化器中创建一个名为that的文件。在本例中,我创建了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

NOTE: I would also like to mention that this sort of monkey patching to get things to work is frowned upon and may break on upgrades so be careful and be fully aware of what it is that you want to do.

注意:我还想说的是,这种为了让事情正常运行而进行的修补工作是不被允许的,而且可能会在升级时中断,所以要小心,要充分意识到你想要做什么。

Updates:

更新:

  • Change timestamp column names from symbol to string per api change. Thanks Techbrunch for bringing this API change to my attention.
  • 根据api的更改,将时间戳列名从符号更改为字符串。谢谢Techbrunch让我注意到这个API改变。

#3


23  

I think NPatel's method is a right approach, but is doing too much in case you only need to change #created_at on a single model. Since the Timestamp module is included in every AR object, you can just override it per model, not globally. Say:

我认为NPatel的方法是一种正确的方法,但是如果您只需要在单个模型上更改#created_at,那么它所做的工作就太多了。由于时间戳模块包含在每个AR对象中,所以您可以按模型覆盖它,而不是全局覆盖。说:

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

Just a FYI :)

仅供参考:)

#4


5  

You could use the beforesave and beforecreate methods to post the DateTime.now to your specified columns.

您可以使用beforecave和beforecreate方法来发布DateTime。现在到指定的列。

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

#5


3  

quick ugly hack, elaborating from Milan Novota's answer: append the following to environment.rb, replacing the values of the CREATED_COL and UPDATED_COL constants with the desired column names:

快速丑陋黑客,阐述从米兰诺维塔的回答:附加以下的环境。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

#6


0  

Or you could just make your own columns (DateTime) and just manually set the created_at column when you create and set the updated_at column when you update. That might be easier than the hack above. That's what I'm gonna do. Better yet, update rails to allow us to change these names.

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

#7


0  

A sol'n which does not use a monkey patch; use the reversible block during your migration:

不使用猴子补丁的sol;在迁移过程中使用可逆转块:

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

#8


0  

The correct syntax for doing this in rails 4.2

在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

#1


4  

There is no simple way to do that. You can accomplish this either by overriding the ActiveRecord::Timestamp module, or by writing your own one to do the magic for you.

没有简单的方法可以做到这一点。您可以通过覆盖ActiveRecord::Timestamp模块或者编写自己的模块来实现这一点。

Here is how the magic works.

这就是魔术的原理。

#2


25  

This can be done via just over writing the ActiveRecord::Timestamp module methods. Not actually overwriting the entire module. I need to to accomplish this same goal as I am working with a legacy database. I am on rails 3 and I have started following a methodology of how to monkey patch my code with over writing rails functionality.

这可以通过编写ActiveRecord::Timestamp模块方法来完成。不是覆盖整个模块。我需要在使用遗留数据库时完成相同的目标。我已经在rails 3上了,并且我已经开始使用一种方法,即如何通过编写rails功能来修改代码。

I first create the base project that I am working with and create a file called that in the initializers. In this case I created active_record.rb. And within the file I put code to override two methods that controlled the timestamp. Below is the sample of my code:

我首先创建我正在处理的基础项目,并在初始化器中创建一个名为that的文件。在本例中,我创建了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

NOTE: I would also like to mention that this sort of monkey patching to get things to work is frowned upon and may break on upgrades so be careful and be fully aware of what it is that you want to do.

注意:我还想说的是,这种为了让事情正常运行而进行的修补工作是不被允许的,而且可能会在升级时中断,所以要小心,要充分意识到你想要做什么。

Updates:

更新:

  • Change timestamp column names from symbol to string per api change. Thanks Techbrunch for bringing this API change to my attention.
  • 根据api的更改,将时间戳列名从符号更改为字符串。谢谢Techbrunch让我注意到这个API改变。

#3


23  

I think NPatel's method is a right approach, but is doing too much in case you only need to change #created_at on a single model. Since the Timestamp module is included in every AR object, you can just override it per model, not globally. Say:

我认为NPatel的方法是一种正确的方法,但是如果您只需要在单个模型上更改#created_at,那么它所做的工作就太多了。由于时间戳模块包含在每个AR对象中,所以您可以按模型覆盖它,而不是全局覆盖。说:

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

Just a FYI :)

仅供参考:)

#4


5  

You could use the beforesave and beforecreate methods to post the DateTime.now to your specified columns.

您可以使用beforecave和beforecreate方法来发布DateTime。现在到指定的列。

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

#5


3  

quick ugly hack, elaborating from Milan Novota's answer: append the following to environment.rb, replacing the values of the CREATED_COL and UPDATED_COL constants with the desired column names:

快速丑陋黑客,阐述从米兰诺维塔的回答:附加以下的环境。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

#6


0  

Or you could just make your own columns (DateTime) and just manually set the created_at column when you create and set the updated_at column when you update. That might be easier than the hack above. That's what I'm gonna do. Better yet, update rails to allow us to change these names.

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

#7


0  

A sol'n which does not use a monkey patch; use the reversible block during your migration:

不使用猴子补丁的sol;在迁移过程中使用可逆转块:

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

#8


0  

The correct syntax for doing this in rails 4.2

在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