2017-12-28 14 views
0

私が質問に飛び込む前に、自分のコードベースの構造について説明しようと思います。 この質問はコメント内のリンクされた質問とは異なります。なぜなら、それはモジュールクラス内のモジュールを含むリストに関係するからです。モジュールを含むすべてのクラスを見つけようとしています

module ParentModule 
    class X 
    end 
end 

2)また、別のモジュールの下にネストされたクラスがあるかもしれません:

ない直接クラス上または1つのレベルのモジュールに

1)の定義は次のようになり、クラスXのがあるかもしれません

module ParentModule 
    module ChildModule 
    class Y 
    end 
    end 
end 

3)また、内部のいくつかのクラスを持つだけのモジュールがあるかもしれません:

module ParentModule 
    module OtherModule 
    def some_awesome_method 
     ..does something 
    end 
    end 
end 

ParentModuleにあるOtherModuleを含むクラスのリストを取得しようとしています。ここではうまく機能し、私がこれまで持っているものです。

include_resources = ->(klass) { 
     begin 
      klass_string = klass.to_s 
      klass_resource = klass_string.constantize 
      klass_string if klass_resource.included_modules.include?(OtherModule) 
     rescue NameError # skip all bad naming and other irrelevant constant loading mishaps 
      next 
     end 
     } 

私はParentModule.constants.find_all(&include_resources)を行うのであれば、私は偉大なOtherModuleを含み、クラスのリストを取得します!しかし残念ながら、#2の例に示すように、子モジュールの下にネストされたクラスを見つけることはできません。だから私はこれをやってみました:

include_resources = ->(klass) { 
     begin 
      klass_string = klass.to_s 
      klass_resource = klass_string.constantize 
      if klass_resource.class == Module 
      return "ParentModule::#{klass_string}".constants.find_all do |module_klass| 
       module_klass.constantize.included_modules.include?(OtherModule) 
      end 
      end 
      klass_string if klass_resource.included_modules.include?(OtherModule) 
     rescue NameError # skip all bad naming and other irrelevant constant loading mishaps 
      next 
     end 
    } 

残念ながら、これは同じリストを返します。

+0

[モジュールを含むクラスのリストを取得する]の可能な重複(https://stackoverflow.com/questions/3917857/get-a-class-that-include-a-module) –

+0

あなたのご意見ありがとうございます。私はサブモジュールを持っているので、この質問は異なります。リンクされた質問はありません。文字通り、私のコードに書かれている事例、試した事柄、うまくいった事例、なかった事例を追加しました。それがあなたの質問をどのようにするかではないので、私は何が分かっているのか分かりません。 – Mongoid

+0

気持ちが悪い、私はただ助けようとしていた。同一の質問でない場合は、「可能な重複」フラグを拒否することができます。あなたはあなたの質問で "私は<この質問を試しました>と言うことができます。なぜなら、" –

答えて

1

[注:@engineersmnkyは、パラメータを使用しないでflat_mapを使用してこれを行う方法を示しています。私はそれを理解するのがより難しいと感じましたが、それはflat_mapの完全に健全な使用であり、価値ある解決策です。コードはhttps://repl.it/@engineersmnky/IllinformedMountainousAnkole.]に投稿されます

次のコードでは、モジュールの逆ツリーを下降させるために再帰を使用しています。結果(最後に表示されます)は正しいので、2つのモジュールにクラスが含まれています。 (私は、例として使用する最小限のモジュールとクラス階層を符号化しました。)

#!/usr/bin/env ruby 

module ParentModule 
    module OtherModule; end 
    class ParentClassYes; include OtherModule; end 
    class ParentClassNo; end 

    module ChildModule 
    class ChildClassYes; include OtherModule; end 
    class ChildClassNo; end 
    end 
end 


def classes_for_module_tree(the_module, matching_classes = []) 
    the_module.constants.each_with_object(matching_classes) \ 
     do |const, matching_classes| 
    value = the_module.const_get(const) 
    if value.is_a?(Class) 
     if value.included_modules.include?(ParentModule::OtherModule) 
     matching_classes << value 
     end 
    elsif value.is_a?(Module) 
     # Here is where we call this method recursively. We suspend collecting 
     # matches for this module, call the method to process the newly found 
     # (sub)module, then use the array returned by that invocation to resume 
     # processing this module. 
     matching_classes = classes_for_module_tree(value, matching_classes) 
    end 
    end 
    matching_classes 
end 


p classes_for_module_tree(ParentModule) 
# prints: [ParentModule::ParentClassYes, ParentModule::ChildModule::ChildClassYes] 
+0

'ParentModule :: OtherModule'の* eigenclass *を使って' Module#included'で自身のインクルージョンを追跡する理由はありますか?それは再帰的な潜水を避けるでしょう。そうでなければ、これはジェネリック(これは私がそれを扱う方法です)のためのものです。なぜターゲットモジュール(この場合は 'ParentModule :: OtherModule')の渡しを許可しないのですか? – engineersmnky

+1

さらに、' flat_map'と 'compact'私の意見では署名の一部である必要はない 'matching_classes'を渡す必要性を避けるでしょう。 [例](https://repl.it/@engineersmnky/IllinformedMountainousAnkole) – engineersmnky

+0

インクルードされたモジュールの配列をインクルードするたびに更新するには、 'included'を使用するのですか?はい、これは別の方法です。再帰の複雑さを回避しますが、このサポートを必要とする各モジュールを変更する必要があります。そして、一般的な使用のために、ターゲットモジュールはパラメータ化されます。 'flat_map'に関しては、この文脈でどのように使用するのですか? –

関連する問題