Get a list/array of child classes from Single Table Inheritance in Rails?

对着背影说爱祢 提交于 2019-12-04 17:10:15

问题


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.


回答1:


Assuming there is at least one of each of object extant in the table:

Object.all.uniq{|x| x.type}.collect(&:type)



回答2:


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)



回答3:


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



回答4:


ParentClass.subclasses.map(&:name)



回答5:


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]



回答6:


This will do it in one SQL query:

# SELECT DISTINCT type FROM objects
Object.uniq.pluck(:type)



回答7:


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.



来源:https://stackoverflow.com/questions/10535507/get-a-list-array-of-child-classes-from-single-table-inheritance-in-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!