私は最近、grapeを使用してAPIを書いているときにおかしな問題に遭遇しました。 グレープはそれとはまったく関係がありません。この記事は、ActiveSupportがどのように機能し、レールで一定の要求を必要としないすべての魔法のおかげで、それを弱める方法について詳しく説明しています。 猫の下で誰が気にしてください。
そのため、クラスがあります-Grape :: Entity、これを使用してAPIでモデルを表示し、継承し、異なるモジュールを接続し、バージョン管理中に異なるモジュールに入ります。 ディレクトリ構造は次のようになります。
./api/ └── path1 ├── entities │ ├── entity1.rb │ └── entity2.rb ├── v1 │ └── entities │ ├── entity1.rb │ └── entity3.rb └── v2 └── entities ├── entity1.rb ├── entity2.rb └── entity3.rb
::Api::Path1::V2::Entity::Entity1
を使用すると、特定のエントリを簡単に見つけることができます。 そして、すべては順調です。このように、モジュールと最終クラスのみがあります。 ただし、常に単独で作業するわけではなく、ネストされたクラスが発生することもあります。
Module1::Module2::Class1::Class2
、これはカットです。ここでは可能ですが、それも何も問題はありません。 ただし、APIの新しいバージョンを作成し、ゼロから作成するものは何でも、古いクラス
::Api::Path1::V3::Entity::Class1::Class2
を継承します。ここで、
V3::Class1 < V1::Class1
です。 そして、ここですべてが突然壊れます。
::Api::Path1:: V3 ::Entity::Class1::Class2
を取得しようとしていますが、
::Api::Path1:: V1 ::Entity::Class1::Class2
ます。 Railsの魔法の典型的な例では、エラーは発生しませんでしたが、適切なクラスを取得できませんでしたが、完全に異なるクラスを取得しました。これは、フルパスがすべての名前で記述されているにもかかわらず
幸いなことに、これはirbに代わる非常に強力な代替手段であるだけでなく、実行可能なコードをステップごとに歩き回り、何も知らないすべての補助クラスのすべてのメソッドに飛び込むことができる素晴らしいデバッガーです。実装、通信など 詳細は
こちら 。
だから:
... binding.pry '::Api::Path1::V3::Entity::Class1::Class2'.constantize ... > step 65: def constantize => 66: ActiveSupport::Inflector.constantize(self) 67: end > step ... @ line 251 ActiveSupport::Inflector
そして、わずか数ステップで、ActiveSupportの世界に飛び込みます。ActiveSupportはクラス名を解析し、その実装を探します。次のようになります。
250 def constantize(camel_cased_word) 251 names = camel_cased_word.split('::') 252 253
ここで何が起こっていますか:
ActiveSupportは、フォーム
::Api::Path1::V2::Entity::Entity1
を別の単語に分割し、それを順番に収集して、親オブジェクトから開始して、次の各名前でconst_getを呼び出し、定義されていることを確認します。
そして、これは、263行目のActiveSupportが
::Api::Path1:: V3 ::Entity::Class1.const_get('Class2')
で、2番目のパラメーターfalseなしで、Class2が継承クラス
::Api::Path1:: V1 ::Entity::Class1
定義されているときに問題が発生する場所
::Api::Path1:: V1 ::Entity::Class1
、そしてそれがメソッドから取得して返すものです。
candidate = constant.const_get(name, false)
を使用する場合、このような問題は存在しませんが、これはバグというよりも機能です。 ActiveSupportは、先祖によって定義されたものを含む定数を見つけようとします。そうしないと、魔法がはるかに少なくなります。
そして、ネストされたクラスを持つクラスを継承しない場合、そのような問題は発生せず、したがって、私たち自身の問題を思い付くことはありません)
追伸
printercuはコメントの中で
素晴らしい記事をアドバイスしまし
た 。