I have a whole bunch of child classes that inherit from a parent class via single-table-inheritance in my Rails app. I'd like a way to get an array of all the child classes that inherit from the main class.
I tried the following single-link command that I found in another SO answer, but it only returns the parent class.
ObjectSpace.each_object(class<<MyParentClass;self;end)
Is there any clean way to do this?
EDIT: Apparently Rails only lazy-loads child classes when called in Dev mode, and possibly production depending on the Rails version. However, the first answer should work on Rails 3.1 and higher in Prod mode.
Rails extends Ruby Class
with the subclasses() method.
In Rails 3 you can call it directly:
YourClass.subclasses
In Rails 2.3, ".subclasses" is protected, so we use have to call it using send()
:
YourClass.send(:subclasses)
You need to eager load the classes, as stated in: https://github.com/rails/rails/issues/3364
ActionDispatch::Reloader.to_prepare do
Rails.application.eager_load!
end
Then you will be able to use:
YourClass.subclasses
or
YourClass.descendants
ParentClass.subclasses.map(&:name)
In your config/environments/development.rb
Rails.application.configure do
config.eager_load = false
end
U can change false to true , and then in your console to do
Class.subclasses
or
Class. descendants
here is the difference between subclasses and descendants
subclasses:
class Foo; end
class Bar < Foo; end
class Baz < Bar; end
Foo.subclasses # => [Bar]
descendants:
class C; end
C.descendants # => []
class B < C; end
C.descendants # => [B]
class A < B; end
C.descendants # => [B, A]
class D < C; end
C.descendants # => [B, A, D]
This will do it in one SQL query:
# SELECT DISTINCT type FROM objects
Object.uniq.pluck(:type)
Note, their is a more efficient way to implement Dave G's method above..
Object.select(:type).map(&:type).uniq
This first sends marshaled objects that only have the "type" attribute from the DB, which takes WAY less memory, then plucks only the types into an array that you can then uniq on. I'm sure there is an infinitely more efficient pure SQL way to do this though.
假设表中至少有一个对象存在:
Object.all.uniq{|x| x.type}.collect(&:type)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.