はじめに
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_at
と updated_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 は実行されません。