如何在ActiveRecord中触摸多个记录?

ohh*_*hho 15 activerecord ruby-on-rails

我想更新updated_at一些记录:

users = User.in_mailing_list
users.update_all(:updated_at => Time.now)
Run Code Online (Sandbox Code Playgroud)

是否有一个快捷方式,比如users.touch_all方法?

Nik*_*rts 9

不确定rhernando的答案是否适用于旧版本的Ruby,但在我看来这是一个更清晰的方法,适用于Ruby 2+

users.each(&:touch)
Run Code Online (Sandbox Code Playgroud)
  • NB.正如评论中所提到的,这将导致N个请求,而不是使用update_all,这将在单个命令中执行.

  • 这将不必要地发出_n_个查询.`users.update_all updated_at:Time.now`用1个查询做. (11认同)
  • @LucasNelson`touch`也不会触发它们.根据文档:`不执行验证,只执行after_touch,after_commit和after_rollback回调.ref:http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-touch (4认同)

Luk*_*uke 8

你可以这样做:

User.update_all({updated_at: Time.now}, {id: user_ids})
Run Code Online (Sandbox Code Playgroud)

注:花括号是必需的,否则尝试设置updated_at id,而不是更新updated_at ,其中 id在user_ids

干杯!

  • 这也可以写成`User.where(id:user_ids).update_all(updated_at:Time.now)` (8认同)

Ole*_*huk 6

如果您需要触摸ActiveRelaton记录,则必须使用update_all方法。它涉及单个事务中的多个记录:

User.update_all(updated_at: Time.current)
User.where(active: true).update_all(active: false)
Run Code Online (Sandbox Code Playgroud)

但是如果你有Array记录,在这种情况下,你只能each使用update

users.each { |user| user.update(active: true) }
Run Code Online (Sandbox Code Playgroud)

这种情况的缺点:对于每个user将是一个单独的交易