This helped me
config.autoload_paths += %W( #{config.root}/app/models/listings )
Taken from here - http://hakunin.com/rails3-load-paths
Вопрос
I have a STI in place for 10 models inheriting from one ActiveRecord::Base
model.
class Listing::Numeric < ActiveRecord::Base
end
class Listing::AverageDuration < Listing::Numeric
end
class Listing::TotalViews < Listing::Numeric
end
There are 10 such models those inherit from Listing::Numeric
In rails console, when I try for .descendants
or .subclasses
it returns an empty array.
Listing::Numeric.descendants
=> []
Listing::Numeric.subclasses
=> []
Ideally this should work.
Any ideas why its not returning the expected subclasses ?
Решение 4
This helped me
config.autoload_paths += %W( #{config.root}/app/models/listings )
Taken from here - http://hakunin.com/rails3-load-paths
Другие советы
This will work only if all the inherited classes are referenced in some running code as rails will load the classes when required then only it will be added as descendants
For eg:
Listing::Numeric.descendants.count
=> 0
Listing::AverageDuration
Listing::TotalViews
Listing::Numeric.descendants.count
=> 2
Old Q, but for anyone else like me who get confused with empty lists for subclasses MyClass.subclasses => []
You need to explicitly set the dependency to your MySubclass class.
class MyClass < ApplicationRecord
end
require_dependency 'my_subclass'
$ MyClass.subclasses
=> ['MySubclass']
https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoloading-and-sti
Execute Rails.application.eager_load!
before calling the .descendants method.
Here is a solution for Rails 7. Originally sourced from RailsGuides, I made modifications to include results even if no data is stored in the table:
module StiPreload
unless Rails.application.config.eager_load
extend ActiveSupport::Concern
included do
cattr_accessor :preloaded, instance_accessor: false
end
class_methods do
def descendants
preload_sti unless preloaded
super
end
def preload_sti
types_from_db = base_class
.unscoped
.select(inheritance_column)
.distinct
.pluck(inheritance_column)
.compact
(types_from_db.present? || types_from_file).each do |type|
type.constantize
end
self.preloaded = true
end
def types_from_file
Dir::each_child("#{Rails.root}/app/models").reduce([]) do |acc, filename|
if filename =~ /^(#{base_class.to_s.split(/(?=[A-Z])/).first.downcase})_(\w+)_datum.rb$/
acc << "#{$1.capitalize}#{$2.classify}"
end
acc
end
end
end
end
end
class YoursTruly < ApplicationRecord
include StiPreload
end
YoursTruly.descendants # => [...]