はじめに
直近のプロジェクトではRails5を使っているのですが、利用しているgem関連で下記のような警告が大量に出力されるので、少し調べてみました。
(「./bin/rails c」や「./bin/bundle exec rspec」を実行すると大量に出力されます。)
1 | DEPRECATIONWARNING:alias_method_chainisdeprecated. |
これは、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 | classHelloUser defhello puts'Hello' end defhello_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 | classHelloUser defhello puts'Hello' end defhello_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 | classHelloUser defhello puts'Hello' end end moduleHelloWithWorld defhello 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なメソッドは、今後のアップデートで利用できなくなることもありますので、しっかりと理解した上で利用し、可能であれば、置き換えていくようにしましょう。