I would like to be able to iterate over and inspect all the models in my rails app. In pseudo-code it would look something like:
rails_env.models.each do |model|
I tried implementing the above solutions under Rails 5 and they didn't quite work. Here's a solution which finds all models which starts with "page_" (or any other prefix; just specify that):
def self.page_models(prefix = "page")
models = []
folder = File.join(Rails.root, "app", "models")
Dir[File.join(folder, "*")].each do |filename|
if filename =~ /models\/#{prefix}/
klass = File.basename(filename, '.rb').camelize.constantize
models << klass
end
end
return models
end
Rails Admin uses this code (see https://github.com/sferik/rails_admin/blob/master/lib/rails_admin/config.rb, method viable_models):
([Rails.application] + Rails::Engine.subclasses.collect(&:instance)).flat_map do |app|
(app.paths['app/models'].to_a + app.config.autoload_paths).collect do |load_path|
Dir.glob(app.root.join(load_path)).collect do |load_dir|
Dir.glob(load_dir + '/**/*.rb').collect do |filename|
# app/models/module/class.rb => module/class.rb => module/class => Module::Class
lchomp(filename, "#{app.root.join(load_dir)}/").chomp('.rb').camelize
end
end
end
end.flatten.reject { |m| m.starts_with?('Concerns::') }
The advantage being that it loads models in associated engines, not just in your current app.
Similar to nathanvda's response, use camelize rather than capitalize to support model files with underscores, and use String#constantize rather than Kernel.const_get.
Additionally, if you keep non-activerecord models in your models folder (e.g. a search class for consolidating search logic), you'll want to check the class is an active record model.
Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|
klass = File.basename(filename, '.rb').camelize.constantize
next unless klass.ancestors.include?(ActiveRecord::Base)
next if klass.abstract_class?
# do something with klass
end
If you are looking at ApplicationRecord models only in a modern Rails application, you can just use
ApplicationRecord.descendants
Here you can have a look at it : http://apidock.com/rails/Class/descendants
Iterate over all files in `$RAILS_ROOT\app\models' ?
For instance
def find_all_models
# iterate over all files in folder
folder = File.join(RAILS_ROOT, "app", "models")
Dir[File.join(folder, "*")].each do |filename|
# remove .rb
model_name = File.basename(filename).sub(/.rb$/, '').capitalize
model = Kernel.const_get(model_name)
# .. do something with your model :)
end
end
Does this help?