Làm cách nào để tạo một cá thể lớp từ một tên chuỗi trong ruby?


121

Tôi có tên của một lớp và tôi muốn tạo một thể hiện của lớp đó để tôi có thể lặp qua từng thuộc tính rails có trong lược đồ của lớp đó.

Tôi sẽ làm điều đó như thế nào?

  1. Tôi có tên là một chuỗi của lớp tôi muốn kiểm tra
  2. Tôi đoán tôi cần khởi tạo một phiên bản lớp để tôi có thể
  3. Lặp qua các thuộc tính của nó và in chúng.

1
Đâ là một câu hỏi tuyệt vời. Cảm ơn cho hỏi nó và tiết kiệm cho tôi từ việc sử dụngeval
David Tây

Câu trả lời:


219

Trong đường ray, bạn chỉ có thể làm:

clazz = 'ExampleClass'.constantize

Trong ruby ​​nguyên chất:

clazz = Object.const_get('ExampleClass')

với các mô-đun:

module Foo
  class Bar
  end
end

bạn sẽ sử dụng

> clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
  => Foo::Bar 
> clazz.new
  => #<Foo::Bar:0x0000010110a4f8> 

4
Lưu ý rằng Object.const_get('Foo::Bar')sẽ không hoạt động, trong khi constantizesẽ.
Marc-André La bất hạnh

Cảm ơn, đã thức dậy để hỏi về điều đó vì vấn đề của Quản trị viên :: Người dùng :) Đánh bại tôi.
mhenrixon

Này @Wes, điều này rất hữu ích, cảm ơn! Câu hỏi nhanh - điều này cũng sẽ hoạt động cho các mô-đun lồng nhau? Ví dụ:clazz = 'Foo::Bar::Uber'
iaacp

@iaacp Có, nó sẽ hoạt động ở nhiều cấp độ lồng nhau như bạn có.
Wes


6

Thử cái này:

Kernel.const_get("MyClass").new

Sau đó, để lặp qua các biến phiên bản của đối tượng:

obj.instance_variables.each do |v|
  # do something
end

Cảm ơn bạn, vì tôi thực sự phải lặp qua các cột của mô hình bản ghi đang hoạt động, điều này sẽ không hiệu quả với tôi nhưng nó sẽ hữu ích trong các ứng dụng ruby ​​"thuần túy" của tôi :)
mhenrixon

1
Kiểm tra ActiveRecord # thuộc tính () và / hoặc ActiveRecord # thuộc tính_names ().
khai thác


5
module One
  module Two
    class Three
      def say_hi
        puts "say hi"
      end
    end
  end
end

one = Object.const_get "One"

puts one.class # => Module

three = One::Two.const_get "Three"

puts three.class # => Class

three.new.say_hi # => "say hi"

Trong ruby ​​2.0 và, có thể là các bản phát hành trước đó, Object.const_getsẽ thực hiện tra cứu một cách đệ quy các không gian tên như Foo::Bar. Ví dụ trên là khi không gian tên được biết trước và nêu bật thực tế là const_getcó thể được gọi trực tiếp trên các mô-đun thay vì chỉ trên Object.


Bạn nên thêm một lời giải thích cho điều này. Hiện tại, nó chỉ là một khối mã.
Josh Crozier
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.