2012-10-28 16 views
6

Tôi đang sử dụng Ruby 1.9.2 và đá quý Ruby on Rails v3.2.2. Tôi muốn "làm tổ" sự bao gồm các mô-đun cho tôi đang sử dụng tính năng RoR ActiveSupport::Concern, nhưng tôi có một nghi ngờ nơi tôi nên nhà nước phương pháp include. Đó là, tôi đã điều sau đây:Làm cách nào để "lồng ghép" các mô-đun khi sử dụng tính năng Mối quan tâm của Ruby on Rails ActiveSupport :: Concern?

module MyModuleA 
    extend ActiveSupport::Concern 

    # include MyModuleB 

    included do 
    # include MyModuleB 
    end 
end 

nên tôi nêu include MyModuleB trong "cơ thể"/"bối cảnh"/"phạm vi" của MyModuleA hay tôi nên nói rõ rằng trong khối included do ... end? Sự khác biệt và những gì tôi nên mong đợi từ đó là gì?

+0

Ghi chú rằng đây không phải là một thực hành tốt ở tất cả. Bạn có thể nhận được vào các phụ thuộc giả mạo giữa thứ tự bao gồm các mô-đun. – geekazoid

Trả lời

16

Nếu bạn bao gồm MyModuleB trong "cơ thể" của MyModuleA, thì chính bản thân mô-đun được mở rộng bằng chức năng của B. Nếu bạn đưa nó vào khối included, thì nó được đưa vào lớp hòa trộn trong MyModuleA.

Đó là:

module MyModuleA 
    extend ActiveSupport::Concern 
    include MyModuleB 
end 

sản xuất cái gì đó như:

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

khi

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

sản xuất cái gì đó như:

class Foo 
    include MyModuleA 
    include MyModuleB 
end 

Lý do cho điều này là ActiveSupport::Concern::included là tương tự như:

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

Mã trong khối included được chạy trong bối cảnh bao gồm lớp, chứ không phải là bối cảnh của mô-đun. Do đó, nếu MyModuleB cần quyền truy cập vào lớp, nó sẽ được trộn vào, sau đó bạn muốn chạy nó trong khối included. Nếu không, nó có hiệu quả giống nhau.

Bằng phương tiện của cuộc biểu tình:

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

Cảm ơn bạn. Tôi đã mở [câu hỏi liên quan mới] (http://stackoverflow.com/questions/13110749/how-to-make-methods-added-by-the-inclusion-of-a-nested-module-to-be-instance) về phương pháp. – Backo

Các vấn đề liên quan