Rails 6 adds ActiveRecord::Relation#touch_all

Amit Choudhary

Amit Choudhary

March 12, 2019

This blog is part of our  Rails 6 series.

Before moving forward, we need to understand what the touch method does. touch is used to update the updated_at timestamp by defaulting to the current time. It also takes custom time or different columns as parameters.

Rails 6 has added touch_all on ActiveRecord::Relation to touch multiple records in one go. Before Rails 6, we needed to iterate all records using an iterator to achieve this result.

Let's take an example in which we call touch_all on all user records.

Rails 5.2

>> User.count
SELECT COUNT(\*) FROM "users"

=> 3

>> User.all.touch_all

=> Traceback (most recent call last):1: from (irb):2
NoMethodError (undefined method 'touch_all' for #<User::ActiveRecord_Relation:0x00007fe6261f9c58>)

>> User.all.each(&:touch)
SELECT "users".* FROM "users"
begin transaction
  UPDATE "users" SET "updated_at" = ? WHERE "users"."id" = ?  [["updated_at", "2019-03-05 17:45:51.495203"], ["id", 1]]
commit transaction
begin transaction
  UPDATE "users" SET "updated_at" = ? WHERE "users"."id" = ?  [["updated_at", "2019-03-05 17:45:51.503415"], ["id", 2]]
commit transaction
begin transaction
  UPDATE "users" SET "updated_at" = ? WHERE "users"."id" = ?  [["updated_at", "2019-03-05 17:45:51.509058"], ["id", 3]]
commit transaction

=> [#<User id: 1, name: "Sam", created_at: "2019-03-05 16:09:29", updated_at: "2019-03-05 17:45:51">, #<User id: 2, name: "John", created_at: "2019-03-05 16:09:43", updated_at: "2019-03-05 17:45:51">, #<User id: 3, name: "Mark", created_at: "2019-03-05 16:09:45", updated_at: "2019-03-05 17:45:51">]

Rails 6.0.0.beta2

>> User.count
SELECT COUNT(*) FROM "users"

=> 3

>> User.all.touch_all
UPDATE "users" SET "updated_at" = ?  [["updated_at", "2019-03-05 16:08:47.490507"]]

=> 3

touch_all returns count of the records on which it is called.

touch_all also takes a custom time or different columns as parameters.

Rails 6.0.0.beta2

>> User.count
SELECT COUNT(*) FROM "users"

=> 3

>> User.all.touch_all(time: Time.new(2019, 3, 2, 1, 0, 0))
UPDATE "users" SET "updated_at" = ?  [["updated_at", "2019-03-02 00:00:00"]]

=> 3

>> User.all.touch_all(:created_at)
UPDATE "users" SET "updated_at" = ?, "created_at" = ?  [["updated_at", "2019-03-05 17:55:41.828347"], ["created_at", "2019-03-05 17:55:41.828347"]]

=> 3

Here is the relevant pull request.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.