はじめに
Rails 6 に追加された新機能を試す第105段。 今回は、 カラム名編です。
Rails 6 では、 pluck
や order
で指定するカラムの書き方が "table"."column"
でも Arel.sql()
で囲いなさいという警告が出なくなりました。
Arel.sql()
で囲っても囲わなくても結果としては変わらないことが理由のようです。
この変更に伴い、 Rails 5.2.3 で出ていたRails 6.0 では禁止となると DEPRECATION WARNING
が出ていたところが、Rails 6.0 で禁止にならず、Rails 6.1 に持ち越されました。
(注意: Rails 6.0.1 がリリースされましたが、動作確認時点での最新版は、Rails 6.0.0 でした。 Rails 6.0.1 では未確認です )
Ruby 2.6.5, Rails 6.0.0, Rails 5.2.3 で確認しました。
また、データベースは、 PostgreSQL 12.0 を使っています。
$ rails --version
Rails 6.0.0
今回は、User モデルを作って、 rails console
で確認します。
Rails プロジェクトを作る
$ rails new rails_sandbox
cd rails_sandbox
User のモデルを作成する
$ bin/rails g model User name
データベースのマイグレーションを実行する
$ bin/rails db:create db:migrate
rails console で確認します。
User.order
の引数を変更して確認します。
name
を指定する
name
を指定したときは、警告は出ません。
irb(main):001:0> User.order("name")
User Load (0.9ms) SELECT "users".* FROM "users" ORDER BY name LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
users.name
を指定する
users.name
を指定したときは、警告は出ません。
irb(main):002:0> User.order("users.name")
User Load (0.9ms) SELECT "users".* FROM "users" ORDER BY users.name LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
"users"."name"
を指定する
"users"."name"
を指定したときも、警告は出ません。
irb(main):003:0> User.order('"users"."name"')
User Load (0.9ms) SELECT "users".* FROM "users" ORDER BY "users"."name" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
name /* comment */
を指定する
name /* comment */
を指定したときは、 DEPRECATION WARNING が出ます。
irb(main):006:0> User.order("name /* comment */")
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "name /* comment */". Non-attribute arguments will be disallowed in Rails 6.1. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql(). (called from irb_binding at (irb):6)
User Load (0.8ms) SELECT "users".* FROM "users" ORDER BY name /* comment */ LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
Rails 5 では
Rails 5.2.3 では、 name /* comment */
を指定したときの他、 "users"."name"
のときも DEPRECATION WARNING が表示されます。
irb(main):003:0> User.order('"users"."name"')
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "\"users\".\"name\"". Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql(). (called from irb_binding at (irb):3)
User Load (0.8ms) SELECT "users".* FROM "users" ORDER BY "users"."name" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
Arel.sql() で囲ってみても結果的に実行されるSQL は、警告が出ていたときと何ら変りありません。
irb(main):005:0> User.order(Arel.sql('"users"."name"'))
User Load (0.9ms) SELECT "users".* FROM "users" ORDER BY "users"."name" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try105_disallow_row_sql