有没有办法避免自动更新Rails的时间戳字段?
如果您有DB列created_at
和updated_at
当您创build和更新模型对象时,Rails将自动设置这些值。 有没有办法保存模型,而不触摸这些列?
我正在引入一些遗留数据,我想从遗留数据字段(不同名称)的相应值中设置这些值。 我发现当我在模型上设置它们,然后保存模型,Rails似乎覆盖了传入的值。
当然,我可以用不同的方式命名Rails模型列来防止这种情况,但是在导入数据之后,我希望Rails能够自动完成时间戳记的工作。
在迁移或rake任务中执行此操作(如果您处于边缘导轨上,则在新的数据库种子中 ):
ActiveRecord::Base.record_timestamps = false begin run_the_code_that_imports_the_data ensure ActiveRecord::Base.record_timestamps = true # don't forget to enable it again! end
您可以安全地设置created_at
和updated_at
手动,Rails不会抱怨。
注意:这也适用于单个模型,例如User.record_timestamps = false
改用update_column方法:
http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
update_column(name, value) # Updates a single attribute of an object, without calling save.
validation被跳过。
callback被跳过。
如果该列可用,updated_at / updated_on列不会更新。
在新对象上调用时引发ActiveRecordError,或者当name属性标记为只读时引发。
您可以在迁移中设置以下内容:
ActiveRecord::Base.record_timestamps = false
或者等待使用update_all:
update_all(updates,conditions = nil,options = {})
更新所有logging与给定的细节,如果他们符合一组条件提供,限制和订单也可以提供。 这个方法构造一个单独的SQL UPDATE语句,并直接发送到数据库。 它不会实例化相关模型,也不会触发Active Recordcallback。
Rails 5提供了一种更新logging而不更新其时间戳updated_at
的方便方法。
你只需要在更新logging时通过touch:false
。
>> user = User.first >> user.updated_at => Thu, 28 Apr 2016 20:01:57 IST +05:30 >> user.name = "Jose" >> user.save(touch: false) => true >> user.updated_at => Thu, 28 Apr 2016 20:01:57 IST +05:30
在Rails 3+中,对于单个对象,请为对象而不是类设置record_timestamps
。 也就是说,
>> user = User.first >> user.updated_at => Tue, 12 Apr 2016 22:47:51 GMT +00:00 >> user.name = "Jose" => "Jose" >> user.record_timestamps = false >> user.save => true >> user.updated_at => Tue, 12 Apr 2016 22:47:51 GMT +00:00 >> User.record_timestamps => true
通过这种方式,您不会触摸模型的全局状态,也不必记住在ensure
块中恢复之前的设置。
由于这是一次性导入,因此您可以执行以下操作:
- 使用
legacy_created_at
和legacy_updated_at
字段创build模型。 - 加载遗留数据。 根据需要映射到模型字段。 你可以使用
#save
,一般不用担心使用update_all
之类的,如果需要的话可以使用callback。 - 创build一个迁移,将列重命名为
created_at
和updated_at
。
不在批量导入时,可以覆盖should_record_timestamps? 方法在您的模型上添加新的检查何时更新updated_at列。
我喜欢使用混合模块暂时closures块中的时间戳:
module WithoutTimestamps def without_timestamps old = ActiveRecord::Base.record_timestamps ActiveRecord::Base.record_timestamps = false begin yield ensure ActiveRecord::Base.record_timestamps = old end end end
那么你可以在任何需要的地方使用它
class MyModel < ActiveRecord::Base include WithoutTimestamps def save_without_timestamps without_timestamps do save! end end end
或者只是这样的一次性的:
m = MyModel.find(1) WithoutTimestamps.without_timestamps do m.save! end
参考其他答案,我发现令我惊讶的是,禁用单个模型的时间戳,如下所示:
User.record_timestamps = false
为我的开发数据库工作,但不是在我的预生产数据库,它运行在不同的服务器上。 但是,如果我禁用所有模型的时间戳,它的工作原理
ActiveRecord::Base.record_timestamps = false
(情况:在迁移中修改created_at属性)
或者,为了线程安全,请参阅: http : //www.hungryfools.com/2007/07/turning-off-activerecord-timestamp.html