はじめに
直近のプロジェクトではRails5を使っているのですが、利用しているgem関連で下記のような警告が大量に出力されるので、少し調べてみました。
(「./bin/rails c」や「./bin/bundle exec rspec」を実行すると大量に出力されます。)
1 | DEPRECATION WARNING: alias_method_chain is deprecated. |
これは、Rails5からはActiveSupportのalias_method_chainが非推奨(deprecated)になり、代わりにModule#prependを使うように促しています。
alias_method_chainとは
まず、deprecatedになったalias_method_chainですが、下記のように利用します。
1 2 3 4 5 6 7 8 9 10 11 | class HelloUser def hello puts 'Hello' end def hello_with_world hello_without_world puts 'World' end alias_method_chain :hello, :world end |
上記のコードは、alias_methodを使った場合は、下記と同等になります。
1 2 3 4 5 6 7 8 9 10 11 12 | class HelloUser def hello puts 'Hello' end def hello_with_world hello_without_world puts 'World' end alias_method :hello_without_world, :hello alias_method :hello, :hello_with_world end |
- helloメソッドがhello_with_worldメソッドに置き換わる。
- 元々のhelloメソッドはhello_without_worldメソッドとして使えるようになる。
実行結果を下記に記載しますが、置き換わっているのがわかると思います。
1 2 3 4 5 6 | [1] pry(main)> hello_user = HelloUser.new [2] pry(main)> hello_user.hello Hello World [3] pry(main)> hello_user.hello_without_world Hello |
Module#prependとは
逆に推奨されているModule#prependの使い方ですが、下記のように使います。
1 2 3 4 5 6 7 8 9 10 11 12 13 | class HelloUser def hello puts 'Hello' end end module HelloWithWorld def hello super puts 'World' end end HelloUser.prepend(HelloWithWorld) |
- prependされた
HelloWithWorldモジュール
は、継承関係上HelloUser
クラスより手前に位置することになる。 - そのため、helloメソッドをオーバーライドしたような形になる。
-
HelloWithWorldモジュール
のメソッド内でsuperを呼び出すことで、元々のメソッドを呼び出すことができる。
実行結果とancestorsメソッドで継承関係を表示しておきます。
ちなみにancestorsメソッドは、クラスやモジュールのスーパークラスとincludeしているモジュールを、優先順で配列に格納して返してくれます。
HelloWithWorld
が
HelloUser
の前にあるのがわかると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [1] pry(main)> hello_user = HelloUser.new [2] pry(main)> hello_user.hello Hello World [3] pry(main)> HelloUser.ancestors => [HelloWithWorld, HelloUser, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, PP::ObjectMixin, RequireAll, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, ActiveSupport::Tryable, Kernel, BasicObject] |
モンキーパッチなどを書くときに利用することになると思います。
(モンキーパッチなんて書かずに、githubにプルリクする方がよいですが。。。)
とりあえず、DEPRECATION WARNINGの出力をなくしたい
Rails5にしたものの、全てのgemに対して、この警告を消すための書き換えの対応をしていくのは大変。
この出力が目障りという方は、
config/application.rb
に追記すれば、消すことができます。
(ただし、自己責任でお願いします。)
1 2 3 4 5 6 7 8 9 10 11 12 | require_relative 'boot' require 'rails/all' # TODO: DEPRECATION WARNING: alias_method_chain is deprecated ActiveSupport::Deprecation.silenced = true # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) ... ... |
さいごに
deprecatedなメソッドは、今後のアップデートで利用できなくなることもありますので、しっかりと理解した上で利用し、可能であれば、置き換えていくようにしましょう。