こんにちは、hachi8833です。
TechRacho記事「Ruby2.0でnil.object_idの値が4から8に変わった理由」の元記事で触れられていたRailsの昔のオプションwhiny_nils
について別途調べてみました。
参考
whiny_nils
オプションはRails 4で廃止された
2008年に公開された上述のBigBinary記事「Why the id of nil is 4 in Ruby」では、Railsのconfig.whiny_nils
オプションについて言及されています。
この設定オプションを調べてみると、Rails 4の段階でdeprecation warningが表示されるようになっていました。
DEPRECATION WARNING: config.whiny_nils option is deprecated and no longer works. (called from block in at /Users/adam/src/sandbox/screencast/config/environments/development.rb:10)
config.eager_load is set to nil. Please update your config/environments/*.rb files accordingly:
さらにRails 4.1で削除され、warningも表示されなくなりました(参考: Rails 4.1リリースノート)。
なおwhinyは「{形} : 泣き言を言う、めそめそした、機嫌の悪い、不機嫌な」だそうです。いかにもnilとの語呂合わせですね。
whiny_nils
が廃止された理由
Rails 4でwhiny_nils
が廃止された理由を調べてみました。
※nil
のオブジェクトIDについては別記事「Ruby2.0でnil.object_idの値が4から8に変わった理由」を参照してください。
ググっただけではそれらしい情報が見当たらなかったので、RailsのGitHubリポジトリを辿ってalindeman/upgradingtorails4のActiveRecordの更新に関する記述を見つけました。
Rails 3から4への移行期に相当します。該当箇所の大意を以下にメモしてみました。
whiny_nils
Rails 4で廃止された
whiny_nils
は、nil
にid
メソッドが送信された場合に警告を表示するためのオプションでした。たとえば@model
が初期化されていない状態で@model.id
を取ろうとしたときに警告されます。Rubyでは初期化されていないインスタンス変数はnil
を返します。Ruby 1.9.3より前は、Objectは
#id
を受信できました。そしてnil
もObjectに属します。特にやっかいだったのは、Ruby 1.9.3より前のnil.id
が実装上の理由から4を返していたことです。このあたりについて詳しくは、Railsのベテラン開発者にお尋ねください。ありがたいことに、Ruby 1.9.3以降はObjectが
#id
を受信しないようになりました。つまりwhiny_nils
オプションはもう必要ないのです。nil.id
を実行すれば普通にNoMethodErrorが表示されます。まぎらわしい警告は表示されません。Railsでは今後、
whiny_nils
オプションがオンになっている場合に非推奨の警告が表示されるようになります。この警告を非表示にしたい場合は、config/environments/development.rb
やconfig/environments/test.rb
からconfig.whiny_nils
を有効にしている行を削除してください。
alindeman/upgradingtorails4の「whiny-nils」より
id
メソッドはRailsのActiveRecordモデルで多用されますが、1.9.3以前のRubyにObject#id
が実装されていたためにモデルオブジェクトのid
がnil
の場合にObject#id
が応答してnil.id
の値である4を返してしまうという問題があったことが推察されます。
モデルオブジェクトがnil
なのにエラーにならないと適切に処理できないので、それを回避するために当時のRailsにconfig.whiny_nils
オプションが導入されていたのですね。
試してみると、Ruby 1.8の時点でもnil.id
を実行すると非推奨の警告が表示されます。Rubyの#id
という標準メソッド名が以前から問題視されていたことがうかがえます。
Ruby 1.9.3で#id
を#object_id
に変更した理由がRailsのActiveRecordのためなのか、Sinatraなど他のフレームワークでも不都合が生じていたからなのかはさらに調べないとわかりませんが、whiny_nils
廃止の理由がこれでわかりました。
RailsガイドのRails アップグレードガイドでは以下のとおりRuby 2.0が推奨されていますが、その理由のひとつがobject_id
に移行したRuby 2.xが必要だからということですね。
Rails 4ではRuby 2.0が推奨されます。Ruby 1.9.3以上が必須です。