Rails6 のちょい足しな新機能を試す106（カラム名編 Part2）

# はじめに

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 を使っています。

```shell
$ rails --version
Rails 6.0.0
```

今回は、 [カラム名編]() をそのまま使って `rails console` で確認していきます。


# rails console で確認する

今回は、 `pluck` を使って確認します。

## カラムに別名をつけた場合

カラムに別名をつけて、 `name as full_name` とした場合は、警告が出ません。

```irb
irb(main):018:0> User.pluck("name as full_name")
   (0.7ms)  SELECT name as full_name FROM "users"
=> []
```

## 関数を使った場合

引数が1つの関数 `char_length` を使った場合は、警告が出ません。

```irb
irb(main):019:0> User.pluck('char_length("name")')
   (0.7ms)  SELECT char_length("name") FROM "users"
=> []
```

## 2つ以上の引数を持つ関数を使った場合

引数が3つの関数 `replace` を使った場合は、警告が出ます。

```irb
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
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
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
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

# 参考情報

* [Allow column name with function (e.g. `length(title)`) as safe SQL string](https://github.com/rails/rails/pull/36448)
* [Allow `column_name AS alias` as safe SQL string](https://github.com/rails/rails/commit/a600d825a56b9ab808eb405f9b8ec91cf131097b)