Rails 实际上内置了这种行为touch
:
User.last.touch
#=> User's updated_at is updated to the current time
在任何配置良好的数据库中处理像这样更新单个列所需的时间应该远低于 5 毫秒,而且很可能低于 1 毫秒。如果您已经准备建立该数据库连接(或者,在 Rails 的情况下,使用以前从池中建立的连接),则开销可以忽略不计。
要回答您的代码是否较慢的问题,那么您认为这一切都是错误的。您可以优化已经非常快速的操作以提高性能,但我反而更担心“正确性”。下面是 ActiveRecordtouch
方法的实现:
def touch(name = nil)
attributes = timestamp_attributes_for_update_in_model
attributes << name if name
unless attributes.empty?
current_time = current_time_from_proper_timezone
changes = {}
attributes.each do |column|
changes[column.to_s] = write_attribute(column.to_s, current_time)
end
changes[self.class.locking_column] = increment_lock if locking_enabled?
@changed_attributes.except!(*changes.keys)
primary_key = self.class.primary_key
self.class.unscoped.update_all(changes, { primary_key => self[primary_key] }) == 1
end
end
现在你告诉我,哪个更快?哪个更正确?
在这里,我给你一个提示:成千上万的人已经使用了这个实现,touch
并且这个代码可能已经运行了数百万次。您的代码已被您单独使用,可能甚至没有编写测试,也没有任何同行评审。
“但仅仅因为其他人使用它并不能使它在经验上变得更好,”你争辩道。当然,你是对的,但它再次忽略了重点:虽然你可以继续构建你的应用程序并制作其他人(你的用户)可以使用并从中受益的东西,但你在这里转动你的轮子,想知道什么对你更好即使其他人已经找到了一个好的解决方案。
把钉子钉在棺材上,是的,你的代码比较慢。它执行回调,进行脏跟踪,并将所有更改的属性保存到数据库中。touch
绕过了大部分,专注于完成将时间戳更新持久化到模型所需的工作。