Ruby on RailsのDEPRECATION WARNINGの出力先を設定するactive_support.deprecation

Railsをバージョンアップするときに、`DEPRECATION WARNING`が出ることがあります。
この警告は「今回のバージョンアップでは影響がないが将来的に無効になる機能」を教えてくれます。

## `DEPRECATION WARNING` の例

例えば Rails 7.1 にバージョンを上げたときに、次の警告が表示されることがあります。

```sh
DEPRECATION WARNING: Passing the coder as positional argument is deprecated and will be removed in Rails 7.2.

Please pass the coder as a keyword argument:

  serialize :namespaces, coder: Psych
 (called from <class:Project> at /home/runner/work/pubannotation/pubannotation/app/models/project.rb:6)
 ```

現在は次のように、ActiveRecordのserializeメソッドの第二引数で`coder`を指定出来ます。

 https://github.com/rails/rails/blob/68eade83c87ae309191add6dfa4959d7d7e07464/activerecord/lib/active_record/attribute_methods/serialization.rb#L183-L194

 ```ruby
 def serialize(attr_name, class_name_or_coder = nil, coder: nil, type: Object, yaml: {}, **options)
  unless class_name_or_coder.nil?
    if class_name_or_coder == ::JSON || [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
      ActiveRecord.deprecator.warn(<<~MSG)
        Passing the coder as positional argument is deprecated and will be removed in Rails 7.2.

        Please pass the coder as a keyword argument:

          serialize #{attr_name.inspect}, coder: #{class_name_or_coder}
      MSG
      coder = class_name_or_coder
    else
```

これが、Rails 7.2では使えなくなる予定であることを教えてくれています。
対応はメッセージの通りです。代わりにキーワード引数を使います。
例えば、次のクラスのように`serialize`の第二引数で`YAML`の値を指定しているのであれば

```ruby
class Project < ActiveRecord::Base
  serialize :namespaces, YAML
```

次のように`coder:`を`YAML`の前に追加します。

```ruby
class Project < ActiveRecord::Base
  serialize :namespaces, coder: YAML
```

## `DEPRECATION WARNING` が出る条件

`rails console`や`rails server`で起動した時に、前述の警告に気がつきませんでした。
CI上のテスト結果を確認しているときに初めて気がつきました。
というのは、`DEPRECATION WARNING`は環境変数`RAILS_ENV`が`development`のときは表示されないからです。
環境変数`RAILS_ENV`が`test`のときはターミナルに表示されます。そのためCIで実行したテスト結果では表示されます。

なぜ環境変数によって表示非表示が変わるのでしょうか？
表題の設定`active_support.deprecation`の値によります。

通常、`config/environments/development.rb`と`config/environments/test.rb`で`active_support.deprecation`が設定されています。


## active_support.deprecation とは

[Rails アプリケーションの設定項目 - Railsガイド](https://railsguides.jp/configuring.html) に次のように記述されています。

> 3.14.12 config.active_support.deprecation
> 非推奨警告メッセージの振る舞いを設定します。指定可能なオプションについてはDeprecation::Behaviorを参照してください。
> 
> デフォルトで生成されるconfig/environments以下のファイルでは、development環境では:logが、test環境では:stderrがそれぞれ設定されます。production環境ではこの設定は無視され、config.active_support.report_deprecationsの設定が使われます。

`config/environments/development.rb`で`active_support.deprecation`が`:log`が設定されています。このため、development環境ではログに出力されます。ターミナルには表示されません。

また、これはデフォルト設定です。
`rails app:update`コマンドを実行して、`config/environments/development.rb`ファイルを更新すると、`active_support.deprecation`の値は`:log`になります。


## 教訓

**Railsのバージョンアップをするときには、テストを実行して `DEPRECATION WARNING` が出ていないことを確認しましょう。**

次回、Railsのバージョンアップをするときには、この教訓を忘れていると思います。ググってこの記事にたどり着いて「そういえば、そうだった！」と思い出すところまでがセットです。そのためにこの記事をセットしておきます。

## 参考

- [DEPRECATION WARNINGが出たらテストを止める #Rails - Qiita](https://qiita.com/taka0125/items/0e32ce241e0c78df9870)
- [Railsの非推奨を分かっているものはあえて無視する #Rails - Qiita](https://qiita.com/satoruk/items/0db42b3e9be7b1228f91)
- [【Ruby on Rails】RSpec導入まで #Ruby - Qiita](https://qiita.com/japwork/items/2a499c5f09cd53838d84)
- [RSpecの準備　 #Ruby - Qiita](https://qiita.com/hryau6/items/746f96ec2419ff62d64b)