2015-02-23 4 views
12

Erweitern auf meine Frage hier (ruby/rails: extending or including other modules), mit meiner bestehenden Lösung, was ist der beste Weg, um festzustellen, ob mein Modul enthalten ist?ruby ​​/ rails: Wie kann man feststellen, ob ein Modul enthalten ist?

Was ich für jetzt getan habe, war ich Instanz Methoden auf jedem Modul so definiert, wenn sie enthalten eine Methode wäre verfügbar, und dann habe ich nur einen Catcher (method_missing()) zu dem übergeordneten Modul, so dass ich fangen kann, wenn sie nicht sind inbegriffen. Meine Lösung Code wie folgt aussieht:

module Features 
    FEATURES = [Running, Walking] 

    # include Features::Running 
    FEATURES.each do |feature| 
    include feature 
    end 

    module ClassMethods 
    # include Features::Running::ClassMethods 
    FEATURES.each do |feature| 
     include feature::ClassMethods 
    end 
    end 

    module InstanceMethods 
    def method_missing(meth) 
     # Catch feature checks that are not included in models to return false 
     if meth[-1] == '?' && meth.to_s =~ /can_(\w+)\z?/ 
     false 
     else 
     # You *must* call super if you don't handle the method, 
     # otherwise you'll mess up Ruby's method lookup 
     super 
     end 
    end 
    end 

    def self.included(base) 
    base.send :extend, ClassMethods 
    base.send :include, InstanceMethods 
    end 
end 

# lib/features/running.rb 
module Features::Running 
    module ClassMethods 
    def can_run 
     ... 

     # Define a method to have model know a way they have that feature 
     define_method(:can_run?) { true } 
    end 
    end 
end 

# lib/features/walking.rb 
module Features::Walking 
    module ClassMethods 
    def can_walk 
     ... 

     # Define a method to have model know a way they have that feature 
     define_method(:can_walk?) { true } 
    end 
    end 
end 

Also meiner Modelle habe ich:

# Sample models 
class Man < ActiveRecord::Base 
    # Include features modules 
    include Features 

    # Define what man can do 
    can_walk 
    can_run 
end 

class Car < ActiveRecord::Base 
    # Include features modules 
    include Features 

    # Define what man can do 
    can_run 
end 

Und dann kann ich

Man.new.can_walk? 
# => true 
Car.new.can_run? 
# => true 
Car.new.can_walk? # method_missing catches this 
# => false 

Habe ich das richtig geschrieben? Oder gibt es einen besseren Weg?

+1

Die Frage ist ein bisschen gewunden, also bin ich nicht sicher, ob dies ist, was Sie suchen, sondern zu prüfen, Wenn ein Modell enthalten ist, können Sie 'object.class.include 'ausführen? Modul' – makhan

+0

Sie können 'respond_to?' Verwenden, um zu prüfen, ob eine Methode verfügbar ist. – Lesleh

Antwort

29

Wenn ich Ihre Frage richtig verstanden habe, können Sie dies tun:

Man.included_modules.include?(Features)? 

Zum Beispiel:

module M 
end 

class C 
    include M 
end 

C.included_modules.include?(M) 
    #=> true 

als

C.included_modules 
    #=> [M, Kernel] 

Andere Möglichkeiten:

als @ Markan erwähnt:

C.include? M 
    #=> true 

oder:

C.ancestors.include?(M) 
    #=> true 

oder gerade:

C < M 
    #=> true 
+0

Upvoted für die 'C makhan

+0

@makhan, es ist die Methode [Modul # <] (http://ruby-doc.org//core-2.2/Module.html#method-i-3C). –

+0

@makhan "Eloquent Ruby" von Russ Olsen ist eine nette (und qiet umfassende) Übersicht über Ruby-Idome. – TNT

Verwandte Themen