在Rails中手动设置updated_at

Tom*_*man 28 ruby-on-rails callback

我正在将我的旧博客帖子迁移到我的新Rails博客中,我希望他们的updated_at属性与我旧博客上的相应值相匹配(而不是他们迁移到我的新Rails博客的日期).

我怎样才能做到这一点?当我updated_at手动设置时,它会被before_save回调覆盖.

注意:此问题仅对Rails <3.2.11有效.较新版本的Rails允许您手动设置时间戳,而不会覆盖它们.

And*_*ell 28

如果它是一次性的东西,你可以打开record_timestamps或关闭.

ActiveRecord::Base.record_timestamps = false

#set timestamps manually

ActiveRecord::Base.record_timestamps = true
Run Code Online (Sandbox Code Playgroud)

当我用我的应用程序遇到这个问题时,我搜索了一下,这似乎对我来说最有意义.这是一个初始化程序,我可以在需要的地方调用:

module ActiveRecord  
  class Base  

    def update_record_without_timestamping  
      class << self  
        def record_timestamps; false; end  
      end  

      save!  

      class << self  
        def record_timestamps; super ; end  
      end  
    end  

  end  
end  
Run Code Online (Sandbox Code Playgroud)

  • 我不希望这在多线程服务器上能很好地工作。 (2认同)

小智 5

从最新版本的Rails(根据iGEL评论3.2.11)开始,您可以在代码中设置updated_at属性,保存时将更改更改.

我假设rails正在跟踪已经手动更改的"脏"属性,而不是在保存时覆盖.

> note = Note.last
  Note Load (1.4ms)  SELECT "notes".* FROM "notes" ORDER BY "notes"."id" DESC LIMIT 1
=> #<Note id: 39, content: "A wee note", created_at: "2015-06-09 11:06:01", updated_at: "2015-06-09 11:06:01">
> note.updated_at = 2.years.ago
=> Sun, 07 Jul 2013 21:20:47 UTC +00:00
> note.save
   (0.4ms)  BEGIN
   (0.8ms)  UPDATE "notes" SET "updated_at" = '2013-07-07 21:20:47.972990' WHERE "notes"."id" = 39
   (0.8ms)  COMMIT
=> true
> note
=> #<Note id: 39, content: "A wee note",  created_at: "2015-06-09 11:06:01", updated_at: "2013-07-07 21:20:47">
Run Code Online (Sandbox Code Playgroud)

如此简短的回答,在最新版本的rails中不再需要解决方法.


San*_*o L 5

我看到两种方法可以轻松完成此操作:

触摸(导轨 >=5)

在 Rails 5 中,您可以使用该touch方法并给出一个命名参数,timetouch 文档所述

foo.touch(time: old_timestamp)
Run Code Online (Sandbox Code Playgroud)

update_column (Rails >=4)

如果您希望在 Rails 4 及更低版本中使用它或想要避免所有回调,您可以使用绕过所有安全或触摸回调和验证update_columnorupdate_columns方法之一

foo.update_column(updated_at, old_timestamp)
Run Code Online (Sandbox Code Playgroud)

或者

foo.update_columns(updated_at: old_timestamp)
Run Code Online (Sandbox Code Playgroud)