Rails6 のちょい足しな新機能を試す22（filter_attributes 編）

# はじめに

Rails 6 に追加されそうな新機能を試す第22段。 今回のちょい足し機能は、 `filter_attributes` ( `filter_attributes=` メソッド)編です。
Rails 6.0 では、 filter_attributes で指定された model の attribute は `[FILTERED]` と表示されるようになります。

Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

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

# Rails プロジェクトを作る

```shell
$ rails new rails6_0_0rc1
$ cd rails6_0_0rc1
```

# User model を作ります

```shell
$ bin/rails g model User name sensitive
$ bin/rails db:create db:migrate
```

# config/initializers/filter_parameter_logging.rb を編集する

sensitive を `[FILTERED]` にするために `filter_parameter_logging.rb` を編集します。

```ruby:config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:password, :sensitive]
```

# irb で確認する

irb で User モデルを作成して、確認すると、 sensitive の値が `[FILTERED]` となっていることがわかります。

```irb
bash-4.4# bin/rails c
Running via Spring preloader in process 50
Loading development environment (Rails 6.0.0.rc1)
irb(main):001:0> user = User.new(name: 'rails', sensitive: 'sensitive')
=> #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
```

`pp` を実行した場合も `[FILTERED]` で表示されます。

```irb
irb(main):002:0> pp user
#<User:0x0000556be6e41c48
 id: nil,
 name: "rails",
 sensitive: [FILTERED],
 created_at: nil,
 updated_at: nil>
=> #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
```

# User model を編集する

`filter_parameter_logging.rb` から `:sensitive` を削除して、 `user.rb` で `filter_attributes=` メソッドを使います。

```ruby:config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:password]
```

```ruby:app/models/user.rb
class User < ApplicationRecord
  self.filter_attributes += [:sensitive]
end
```

# 再度 irb で確認する

irb で User モデルを作成して、確認すると、 sensitive の値が `[FILTERED]` となっていることがわかります。

```irb
bash-4.4# bin/rails c
Running via Spring preloader in process 50
Loading development environment (Rails 6.0.0.rc1)
irb(main):001:0> user = User.new(name: 'rails', sensitive: 'sensitive')
=> #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
```

`pp` を実行した場合も `[FILTERED]` で表示されます。

```irb
irb(main):002:0> pp user
#<User:0x0000556be6e41c48
 id: nil,
 name: "rails",
 sensitive: [FILTERED],
 created_at: nil,
 updated_at: nil>
=> #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
```

# filter_parameters で指定した場合と model の filter_attributes で指定した場合の違い

`Rails.application.config.filter_parameters` で指定した場合は、全てのモデルでその attribute が `[FILTERED]` で表示されます。( `Rails.application.config.filter_attributes` で設定されているものが、 `filter_attributes` に反映されます。)

`filter_attributes` で指定した場合は、指定した model の属性だけが `[FILTERED]` になります。

基本的には、 `Rails.application.config.filter_parameters` で指定した方が漏れがなくて良いと思います。

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try022_filter_parameters

# 追記

正規表現による attribute の指定も可能になってます（ `/sens/` を指定すると `sensitive` が `[FILTERED]` になる）。

# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Configuration item config.filter_parameters could also filter out sensitive values of database columns when call #inspect](https://github.com/rails/rails/pull/33756)
* [Implement AR#inspect using ParameterFilter](https://github.com/rails/rails/pull/34208)

# 追記２（2019/09/24)

モデルで save メソッドなどで、保存したときの SQL文は、Filter されずにそのまま出力されます。
sensitive カラムの値、`sensitive` は、モデルの情報として、 [FILTERED] になっていますが、SQL文は、[FILTERED]とはならず、`sensitive` がそのまま出力されます。

```irb
irb(main):001:0> u = User.new(name: 'rails', sensitive: 'sensitive')
=> #<User id: nil, name: "rails", sensitive: [FILTERED], created_at: nil, updated_at: nil>
irb(main):002:0> u.save
   (0.2ms)  BEGIN
  User Create (0.5ms)  INSERT INTO "users" ("name", "sensitive", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "rails"], ["sensitive", "sensitive"], ["created_at", "2019-09-24 12:00:43.525329"], ["updated_at", "2019-09-24 12:00:43.525329"]]
   (8.1ms)  COMMIT
=> true
```