Tech Racho エンジニアの「?」を「!」に。
  • 開発

Rails4で`whiny_nils`オプションが廃止された理由

こんにちは、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は、nilidメソッドが送信された場合に警告を表示するためのオプションでした。たとえば@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.rbconfig/environments/test.rbからconfig.whiny_nilsを有効にしている行を削除してください。
alindeman/upgradingtorails4の「whiny-nils」より

idメソッドはRailsのActiveRecordモデルで多用されますが、1.9.3以前のRubyにObject#idが実装されていたためにモデルオブジェクトのidnilの場合に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以上が必須です。

関連記事(BigBinaryシリーズ)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。