![](/img/trans.png)
[英]Sum the difference between created_at and updated_at (Rails ActiveRecord - Looking for a better way)
[英]Renaming the created_at, updated_at columns of ActiveRecord/Rails
我想重命名 timestamp.rb 中定義的時間戳列。 可以覆蓋timestamp.rb的方法嗎? 以及在使用具有覆蓋方法的模塊的應用程序中必須做什么。
我認為 NPatel 的方法是一種正確的方法,但是如果您只需要在單個模型上更改 #created_at,它就做得太多了。 由於 Timestamp 模塊包含在每個 AR 對象中,您可以根據模型而不是全局覆蓋它。
<= 導軌 5.0
class User < ActiveRecord::Base
...
private
def timestamp_attributes_for_create
super << :registered_at
end
end
導軌 ~> 5.1
private_class_method
def self.timestamp_attributes_for_create
# only strings allowed here, symbols won't work, see below commit for more details
# https://github.com/rails/rails/commit/2b5dacb43dd92e98e1fd240a80c2a540ed380257
super << 'registered_at'
end
end
這可以通過編寫 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
注意:我還想提一下,這種使事情正常工作的猴子補丁是不受歡迎的,並且可能會在升級時中斷,因此請小心並充分了解您想要做什么。
更新:
Rails >= 5.1的更新 anwser 。 我建議使用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
請注意,如果您不想為所有模型配置它,您也可以在特定模型上使用此模塊。
另請注意,您應該使用字符串而不是符號。
您可以使用 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
快速丑陋的 hack,從 Milan 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
沒有簡單的方法可以做到這一點。 您可以通過覆蓋 ActiveRecord::Timestamp 模塊或編寫自己的模塊來實現這一點。
這是魔法的工作原理。
在 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
一個不使用猴子補丁的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
或者,您可以創建自己的列 (DateTime),並在創建時手動設置 created_at 列並在更新時設置 updated_at 列。 這可能比上面的 hack 更容易。 這就是我要做的。 更好的是,更新 rails 以允許我們更改這些名稱。
在 Rails 6.0 中,實例方法timestamp_attributes_for_create
不再存在。 這個方法被推到了類方法級別,現在是私有的
https://apidock.com/rails/v6.0.0/ActiveRecord/Timestamp/ClassMethods/timestamp_attributes_for_create
此更改引入了此提交https://github.com/rails/rails/commit/77ff9a0adbd1318b45203a76c64561b115245603
您仍然可以覆蓋self.timestamp_attributes_for_create
但我強烈建議不self.timestamp_attributes_for_create
,因為私有 API 可以在沒有進一步通知或更大版本顛簸的情況下更改。
對於 Rails 6,我沒有看到定義自定義created_at
/ updated_at
列的給定“Rails 方式”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.