Tìm các lớp học có sẵn trong một Mô-đun


75

Tôi có một mô-đun MyModule. Tôi tự động tải các lớp vào đó. Làm cách nào để có được danh sách các lớp được xác định trong không gian tên của nó?

Thí dụ:

def load_plugins
  Dir.glob(File.dirname(__FILE__) + '/plugins/*.rb') do |f|
    MyModule.class_eval File.read(f)
  end

  # now how can I find the new classes I've loaded into MyModule?
end

Tôi nên nói rằng mỗi fcái chứa một cái gì đó như "lớp Foo; end".

Bạn cũng có thể nghĩ về nó như thế này: trong Rails, làm cách nào để tôi có thể tìm thấy theo chương trình tất cả các lớp được xác định trong mô-đun ActiveRecord?

Câu trả lời:


128

Các lớp được truy cập thông qua các hằng số. Các lớp được xác định trong một mô-đun được liệt kê dưới dạng các hằng số trong mô-đun đó. Vì vậy, bạn chỉ cần chọn các hằng số tham chiếu đến các lớp.

MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}

7
Một điều: tại sao bạn sử dụng bài kiểm tra đó thay vì "MyModule.const_get (c) .is_a? Class"? Tôi không quen với việc sử dụng "===" như vậy.
joshuaxls

3
Không có lý do thuyết phục. Phiên bản === dễ đọc hơn đối với tôi. Sử dụng is_a? sẽ hoạt động tốt.
Chuck

6
Tránh sử dụng rõ ràng toán tử bình đẳng trường hợp ===. Như tên gọi của nó, nó có nghĩa là được sử dụng ngầm trong các casebiểu thức và bên ngoài chúng, nó mang lại một số mã khá khó hiểu. [Hướng dẫn phong cách ]
James Fernandes

Không biết tại sao nhưng điều này không hoạt động trên các mô-đun tích hợp sẵn của Ruby như Kernel, Comp Compare và Enumerable.
vishnuprasanth

1
@Vizkrig: AFAIK những mô-đun đó không được phép có bất kỳ lớp nào trong đó. Nếu bạn đang tìm kiếm các lớp bao gồm một mô-đun, thay vì các lớp nằm trong một mô-đun, đó là một câu hỏi khác .
Chuck

1

Nếu bạn đang ở trên đường ray, trước tiên bạn cần truy cập vào các hằng số để chúng hiển thị, vì chúng được tải một cách lười biếng.

MyModule::NotAClass = "not a class"

MyModule.constants => [:NotAClass]

MyModule::AClass => :AClass # Access class for it to be autoloaded

MyModule.constants => [:AClass, :NotAClass]

# Now, select the constants which are class instances

MyModule.constants
        .map(&MyModule.method(:const_get))
        .select { |constant| constant.is_a? Class} 

 => [MyModule::AClass]**
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.