Ruby
Rails
Rails6

Rails6 のちょい足しな新機能を試す7(touch_all 編)


はじめに

Rails 6 に追加されそうな新機能を試す第7段。 今回のちょい足し機能は、日時を(現在時刻に)一気に更新するメソッド touch_all 編です。

記載時点では、Rails は 6.0.0.beta3 です。 gem install rails --prerelease でインストールできます。

$  rails --version

Rails 6.0.0.beta3


単純な model を作る

新機能を試すために、Book model を作ります。出版時刻なんてあるのかよというツッコミは無しでお願いします。

$ rails new sandbox_6_0_0b3

$ cd sandbox_6_0_0b3
$ rails g model Book title published_at:datetime
$ rails db:migrate

データ 2件作ります。

$ bin/rails c

irb(main):001:0> Book.new(title: 'Ruby Book', published_at: Time.now - 10.year).save
(0.2ms) BEGIN
Book Create (0.4ms) INSERT INTO "books" ("title", "published_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["title", "Ruby Book"], ["published_at", "2009-04-24 11:23:20.452962"], ["created_at", "2019-04-24 11:23:20.474368"], ["updated_at", "2019-04-24 11:23:20.474368"]]
(1.2ms) COMMIT
=> true
irb(main):002:0> Book.new(title: 'Rails Book', published_at: Time.now - 5.year).save
(0.4ms) BEGIN
Book Create (0.7ms) INSERT INTO "books" ("title", "published_at", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["title", "Rails Book"], ["published_at", "2014-04-24 11:23:41.370049"], ["created_at", "2019-04-24 11:23:41.370751"], ["updated_at", "2019-04-24 11:23:41.370751"]]
(7.2ms) COMMIT
=> true
irb(main):003:0> Book.all
Book Load (0.7ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[
#<Book id: 2, title: "Ruby Book", published_at: "2009-04-24 11:23:20", created_at: "2019-04-24 11:23:20", updated_at: "2019-04-24 11:23:20">,
#<Book id: 3, title: "Rails Book", published_at: "2014-04-24 11:23:41", created_at: "2019-04-24 11:23:41", updated_at: "2019-04-24 11:23:41">
]>
irb(main):005:0>

touch_all を使ってみます。 (Book.all の結果はわかりやすいように改行を入れました。)


引数なしで touch_all

touch_all を引数なしで実行すると updated_at が現在時刻に更新されます。

irb(main):007:0> Book.all.touch_all

Book Update All (7.6ms) UPDATE "books" SET "updated_at" = $1 [["updated_at", "2019-04-24 11:38:54.990656"]]
=> 2
irb(main):008:0> Book.all
Book Load (0.8ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[
#<Book id: 2, title: "Ruby Book", published_at: "2009-04-24 11:23:20", created_at: "2019-04-24 11:23:20", updated_at: "2019-04-24 11:38:54">,
#<Book id: 3, title: "Rails Book", published_at: "2014-04-24 11:23:41", created_at: "2019-04-24 11:23:41", updated_at: "2019-04-24 11:38:54">
]>


touch_all(column)

touch_all の引数にカラムを指定すると指定したカラムと updated_at が現在時刻に更新されます。

where と組み合わせることもできます。

(Ruby Book の published_atupdated_at が現在時刻に更新されます。)

irb(main):009:0> Book.where(title: 'Ruby Book').touch_all(:published_at)

Book Update All (8.2ms) UPDATE "books" SET "updated_at" = $1, "published_at" = $2 WHERE "books"."title" = $3 [["updated_at", "2019-04-24 11:40:16.201803"], ["published_at", "2019-04-24 11:40:16.201803"], ["title", "Ruby Book"]]
=> 1
irb(main):010:0> Book.all
Book Load (0.7ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[
#<Book id: 3, title: "Rails Book", published_at: "2014-04-24 11:23:41", created_at: "2019-04-24 11:23:41", updated_at: "2019-04-24 11:38:54">,
#<Book id: 2, title: "Ruby Book", published_at: "2019-04-24 11:40:16", created_at: "2019-04-24 11:23:20", updated_at: "2019-04-24 11:40:16">
]>


touch_all(column1, column2, ...)

touch_all の引数に複数のカラムを指定することもできます。

(Rails Book の created_at , updated_at , published_at が現在時刻に更新されます。)

irb(main):011:0> Book.where(title: 'Rails Book').touch_all(:published_at, :created_at)

Book Update All (7.8ms) UPDATE "books" SET "updated_at" = $1, "published_at" = $2, "created_at" = $3 WHERE "books"."title" = $4 [["updated_at", "2019-04-24 11:54:03.981679"], ["published_at", "2019-04-24 11:54:03.981679"], ["created_at", "2019-04-24 11:54:03.981679"], ["title", "Rails Book"]]
=> 1
irb(main):012:0> Book.all
Book Load (0.9ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[
#<Book id: 2, title: "Ruby Book", published_at: "2019-04-24 11:40:16", created_at: "2019-04-24 11:23:20", updated_at: "2019-04-24 11:40:16">,
#<Book id: 3, title: "Rails Book", published_at: "2019-04-24 11:54:03", created_at: "2019-04-24 11:54:03", updated_at: "2019-04-24 11:54:03">
]>


touch_all(column1, column2,..., time: xxx)

touch_all の引数に time: xxxx で指定した時刻に更新することもできます。

(Rails Book の created_at , updated_at , published_at が 3年前に更新されます。)

irb(main):013:0> Book.where(title: 'Rails Book').touch_all(:published_at, :created_at, time: Time.now - 3.year)

Book Update All (7.3ms) UPDATE "books" SET "updated_at" = $1, "published_at" = $2, "created_at" = $3 WHERE "books"."title" = $4 [["updated_at", "2016-04-24 11:59:16.030048"], ["published_at", "2016-04-24 11:59:16.030048"], ["created_at", "2016-04-24 11:59:16.030048"], ["title", "Rails Book"]]
=> 1
irb(main):014:0> Book.all
Book Load (0.8ms) SELECT "books".* FROM "books" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation
[
#<Book id: 2, title: "Ruby Book", published_at: "2019-04-24 11:40:16", created_at: "2019-04-24 11:23:20", updated_at: "2019-04-24 11:40:16">,
#<Book id: 3, title: "Rails Book", published_at: "2016-04-24 11:59:16", created_at: "2016-04-24 11:59:16", updated_at: "2016-04-24 11:59:16">
]>
irb(main):015:0>


touch_all 実行時の callback や validation

touch_all は内部で update_all を呼び出していて、touch_all が実行されるときに、callback や validation は実行されません。


参考情報