ruby chuyển đổi tên lớp trong chuỗi thành lớp thực tế


87

Làm cách nào để gọi một lớp từ một chuỗi chứa tên lớp đó bên trong nó? (Tôi đoán tôi có thể làm trường hợp / khi nào nhưng điều đó có vẻ xấu.)

Lý do tôi hỏi là vì tôi đang sử dụng acts_as_commentableplugin, trong số những plugin khác, và những plugin này lưu trữ commentable_type dưới dạng một cột. Tôi muốn có thể gọi bất kỳ lớp có thể bình luận cụ thể nào để thực hiện find(commentable_id)trên đó.

Cảm ơn.

Câu trả lời:


131

Tôi nghĩ những gì bạn muốn là constantize

Đó là một cấu trúc RoR. Tôi không biết nếu có một cái cho lõi ruby


hoàn hảo, đó chỉ là những gì tôi đang tìm kiếm.
không được sắp xếp

40
Đối với Ruby đơn giản, bạn sẽ sử dụng Module.const_get. Ưu điểm của constantizenó là nó hoạt động ngay cả với các không gian tên lồng nhau sâu sắc, vì vậy bạn có thể làm 'Functional::Collections::LazyList'.constantizevà lấy LazyList lớp từ Bộ sưu tập mô-đun trong mô-đun Chức năng, trong khi với const_get, bạn phải làm điều gì đó giống như vậy 'Functional::Collections::LazyList'.split('::').reduce(Module, :const_get).
Chuck

45
"Object".constantize # => Object

Hãy lưu ý rằng .constantizelà một phương pháp Rails, bạn sẽ không tìm thấy nó trong đồng bằng của Ruby
Edgar Ortega

34

Cho một chuỗi, trước tiên hãy gọi phân loại để tạo tên lớp (vẫn là một chuỗi), sau đó gọi hằng số để cố gắng tìm và trả về hằng số tên lớp (lưu ý rằng tên lớp là hằng số ).

some_string.classify.constantize

10
Bạn nên sử dụng camelize thay vì phân loại vì phân loại dành cho tên bảng và không xử lý đa dạng hóa tốt.
Peter Brown,

1
Cảm ơn! thật tuyệt!
duykhoa 26/03/13

2
Câu trả lời của bạn thực sự có giá trị, nhưng bạn nên sử dụng "titleize" cho tên bảng bao gồm theo khoảng trắng và xóa khoảng trắng khỏi chuỗi để tạo ý nghĩa cho tên lớp đầy đủ.
SSR

22

Tôi biết đây là một câu hỏi cũ nhưng tôi chỉ muốn để lại ghi chú này, nó có thể hữu ích cho những người khác.

Trong Ruby đơn giản, Module.const_getcó thể tìm thấy các hằng số lồng nhau. Ví dụ, có cấu trúc sau:

module MyModule
  module MySubmodule
    class MyModel
    end
  end
end

Bạn có thể sử dụng nó như sau:

Module.const_get("MyModule::MySubmodule::MyModel")
MyModule.const_get("MySubmodule")
MyModule::MySubmodule.const_get("MyModel")

7

Khi ActiveSupport khả dụng (ví dụ như trong Rails): String#constantizehoặc String#safe_constantize, nghĩa là "ClassName".constantize.

Trong Ruby thuần túy:, Module#const_getđiển hình là Object.const_get("ClassName").

Trong những viên hồng ngọc gần đây, cả hai đều hoạt động với các hằng số được lồng trong các mô-đun, như trong Object.const_get("Outer::Inner").


6

Nếu bạn muốn chuyển đổi chuỗi thành tên lớp actuall để truy cập mô hình hoặc bất kỳ lớp nào khác

str = "group class"

> str.camelize.constantize 'or'
> str.classify.constantize 'or'
> str.titleize.constantize

Example :
  def call_me(str)
    str.titleize.gsub(" ","").constantize.all
  end

Call method : call_me("group class")

Result:
  GroupClass Load (0.7ms) SELECT `group_classes`.* FROM `group_classes`
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.