Ответ 1
Предполагая, что по крайней мере один из каждого из существующих объектов в таблице:
Object.all.uniq{|x| x.type}.collect(&:type)
У меня есть целая куча дочерних классов, которые наследуются от родительского класса через однонаправленное наследование в моем приложении Rails. Мне нужен способ получить массив всех дочерних классов, которые наследуются от основного класса.
Я попробовал следующую команду с одной связью, которую я нашел в другом ответе SO, но возвращает только родительский класс.
ObjectSpace.each_object(class<<MyParentClass;self;end)
Есть ли какой-либо чистый способ сделать это?
EDIT: По-видимому, Rails только ленивы нагружает дочерние классы при вызове в режиме Dev и, возможно, в зависимости от версии Rails. Однако первый ответ должен работать с Rails 3.1 и выше в режиме Prod.
Предполагая, что по крайней мере один из каждого из существующих объектов в таблице:
Object.all.uniq{|x| x.type}.collect(&:type)
Rails расширяет Ruby Class
с помощью метода подклассов().
В Rails 3 вы можете вызвать его напрямую:
YourClass.subclasses
В Rails 2.3 ".subclasses" защищен, поэтому мы должны позвонить ему с помощью send()
:
YourClass.send(:subclasses)
Вам нужно загружать классы, как указано в: https://github.com/rails/rails/issues/3364
ActionDispatch::Reloader.to_prepare do
Rails.application.eager_load!
end
Затем вы сможете использовать:
YourClass.subclasses
или
YourClass.descendants
ParentClass.subclasses.map(&:name)
Это будет сделано в одном запросе SQL:
# SELECT DISTINCT type FROM objects
Object.uniq.pluck(:type)
Обратите внимание, что это более эффективный способ реализации метода Dave G выше..
Object.select(:type).map(&:type).uniq
Это сначала отправляет маршалированные объекты, которые имеют только атрибут "type" из БД, который берет WAY меньше памяти, а затем сбрасывает только типы в массив, который вы можете затем uniq. Я уверен, что есть еще более эффективный чистый SQL-способ сделать это, хотя.