Rubyにおいて、ゲッターとセッターの両方の役割を果たすメソッドを作成することは一般的な設計パターンです。例えば、値が渡された場合は設定を更新し、値が提供されない場合は現在の設定を返すというメソッドがあります。しかし、`value = nil`のような標準的なデフォルト引数を使用すると、論理的な競合が発生します。つまり、ユーザーが設定をクリアするために意図的に`nil`を渡しているのか、あるいは現在の設定を読み取るために何も渡していないのかを、コードが区別できなくなるのです。どちらの場合も`value`は`nil`になりますが、メソッドの契約においては異なる意図を表しています。

Chris Zempelのポートレート
Chris Zempel。Ruby開発者であり、この技術記事の著者。www.aha.io

この記事では特定のRubyプログラミング技術について論じており、Chris Zempelはこの技術的知見の主な著者/ソースです。

この問題を解決するために、開発者はしばしば`NOT_PROVIDED = Object.new.freeze`のような固有の定数を作成し、入力がその特定のオブジェクトと一致するかどうかを確認するという手法をとります。この方法は効果的ですが、余分なボイラープレートを導入し、追加の定数を管理する必要が出てきます。より簡潔な手法として、Rubyがデフォルト引数を評価する方法を活用するテクニックがあります。`def cloaking(value = (nothing_provided = true))`のように、代入を含むデフォルト引数を持つメソッドを定義することで、開発者は引数が省略されたときにのみトリガーされるローカルフラグを作成できます。

この仕組みが機能するのは、Rubyが呼び出し側から入力がない場合にのみデフォルト引数の式を評価するためです。そのシナリオでは、`nothing_provided`は`true`に設定され、`value`も`true`になります。もし呼び出し側が、たとえ`nil`や`false`であっても何らかの引数を提供した場合、Rubyはデフォルトの式を完全にスキップします。これらのケースでは、ローカル変数`nothing_provided`は依然として存在しますが、代入が実行されないため`nil`のままとなります。これにより、メソッドは引数が本当に欠落していたかどうかに基づいてロジックを分岐させることができます。このパターンは、Railsフレームワークの`index_with`メソッドにおいて、オプションのデフォルト値やブロックのロジックを処理するために顕著に使用されています。

その有用性にもかかわらず、このテクニックは特殊なアプローチであり、標準的なRubyのセッター構文を使用するよりもクリーンではないと主張する開発者もいます。デフォルト引数内での代入トリックは、二重目的のメソッドを処理するための巧妙な方法を提供しますが、それは明示的なメソッドのオーバーロードよりも直感的ではない可能性のある、Rubyインタプリタの特定の挙動に依存しています。多くのユースケースでは、値を取得するためのメソッドと設定するためのメソッドを個別に定義するといった標準的なRubyの慣習が、明確で読みやすいコードを維持するための好ましい方法であり続けています。