はじめに
Rails 6 に追加された新機能を試す第106段。 今回は、 カラム名編 Part2です。
Rails 6 では、 pluck
や order
で指定するカラムが、別名を持っている場合や引数一つまたは0の関数の場合も Arel.sql()
で囲いなさいという警告が出なくなりました。
なんでもかんでも警告を出すより、本当に問題になりそうな場合に限定して警告を出す方が、警告の効果があるだろうということのようです。
この変更に伴い、 Rails 5.2.3 で出ていたRails 6.0 では禁止となると DEPRECATION WARNING
が出ていたところが、Rails 6.0 で禁止にならず、Rails 6.1 に持ち越されました。
Ruby 2.6.5, Rails 6.0.0, Rails 5.2.3 で確認しました。
また、データベースは、 PostgreSQL 12.0 を使っています。
$ rails --version
Rails 6.0.0
今回は、 カラム名編 をそのまま使って rails console
で確認していきます。
rails console で確認する
今回は、 pluck
を使って確認します。
カラムに別名をつけた場合
カラムに別名をつけて、 name as full_name
とした場合は、警告が出ません。
irb(main):018:0> User.pluck("name as full_name")
(0.7ms) SELECT name as full_name FROM "users"
=> []
関数を使った場合
引数が1つの関数 char_length
を使った場合は、警告が出ません。
irb(main):019:0> User.pluck('char_length("name")')
(0.7ms) SELECT char_length("name") FROM "users"
=> []
2つ以上の引数を持つ関数を使った場合
引数が3つの関数 replace
を使った場合は、警告が出ます。
irb(main):020:0> User.pluck(%q{replace("name", 'foo', 'bar')})
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "replace(\"name\", 'foo', 'bar')". 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):20)
(0.8ms) SELECT replace("name", 'foo', 'bar') FROM "users"
=> []
Rails 5 では
Rails 5.2.3 では、 いずれの場合も警告が出ます。
irb(main):001:0> User.select("name as full_name")
User Load (0.4ms) SELECT name as full_name FROM "users" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):002:0> User.pluck("name as full_name")
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "name as full_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):2)
(0.9ms) SELECT name as full_name FROM "users"
=> []
irb(main):003:0> User.pluck('char_length("name")')
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "char_length(\"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)
(3.8ms) SELECT char_length("name") FROM "users"
=> []
irb(main):005:0> User.pluck(%q{replace("name", 'foo', 'bar')})
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "replace(\"name\", 'foo', 'bar')". 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):5)
(0.9ms) SELECT replace("name", 'foo', 'bar') FROM "users"
=> []
試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try105_disallow_row_sql