2012-10-28 5 views
6

Ich verwende Ruby 1.9.2 und Ruby on Rails v3.2.2 gem. Ich würde gerne die Aufnahme von Modulen verschachteln, wenn ich die RoR ActiveSupport::Concern Funktion verwende, aber ich habe Zweifel, wo ich die include Methode angeben sollte. Das heißt, ich habe folgenden:Wie "schachteln" Sie die Einbeziehung von Modulen, wenn Sie das ActiveSupport :: Concern-Feature von Ruby on Rails verwenden?

module MyModuleA 
    extend ActiveSupport::Concern 

    # include MyModuleB 

    included do 
    # include MyModuleB 
    end 
end 

Sollte ich feststellen, include MyModuleB im "Körper"/"Kontext"/"scope" von MyModuleA oder soll ich, dass in den included do ... end Block angeben? Was ist der Unterschied und was sollte ich davon erwarten?

+0

Beachten Sie, dass dies überhaupt keine gute Praxis ist. Sie können in falsche Abhängigkeiten zwischen der Reihenfolge der Aufnahme der Module geraten. – geekazoid

Antwort

16

Wenn Sie MyModuleB im "body" von MyModuleA einschließen, dann ist es das Modul selbst, das mit B's Funktionalität erweitert wird. Wenn Sie es in den Block included aufnehmen, ist es in der Klasse enthalten, die MyModuleA mischt.

Das heißt:

module MyModuleA 
    extend ActiveSupport::Concern 
    include MyModuleB 
end 

produziert so etwas wie:

MyModuleA.send :include, MyModuleB 
class Foo 
    include MyModuleA 
end 

während

module MyModuleA 
    extend ActiveSupport::Concern 
    included do 
    include MyModuleB 
    end 
end 

produziert so etwas wie:

class Foo 
    include MyModuleA 
    include MyModuleB 
end 

Der Grund dafür ist, dass ActiveSupport::Concern::included ist analog zu:

def MyModuleA 
    def self.included(klass, &block) 
    klass.instance_eval(&block) 
    end 
end 

Der Code im included Block im Rahmen der mit der Klasse ausgeführt wird, anstatt der Kontext des Moduls. Wenn MyModuleB also Zugriff auf die Klasse benötigt, in die es eingemischt wird, möchten Sie es im Block included ausführen. Ansonsten ist es effektiv das Gleiche.

Durch Demonstration:

module A 
    def self.included(other) 
    other.send :include, B 
    end 
end 

module B 
    def self.included(other) 
    puts "B was included on #{other.inspect}" 
    end 
end 

module C 
    include B 
end 

class Foo 
    include A 
end 

# Output: 
# B was included on C 
# B was included on Foo 
+0

Danke. Ich habe eine [neue verwandte Frage] (http://stackoverflow.com/questions/13110749/how-to-make-methods-added-by-inclusion-of-a-nested-module-to-be-instance) geöffnet) auf Methoden. – Backo

Verwandte Themen