views:

44

answers:

2

Rails does model loading on demand. For a rake task that I'm writing, I need to be able to iterate over all ActiveRecord::Base instances (which is possible with ActiveRecord::Base.send(:subclasses)).

However, for the above to work, they have to already be loaded. Anyone know of a way to force all models to load? Ideally I'd like to not have to poke through app/models since I'd like to catch models added by plugins as well.

A: 

Not sure if I got you right, but I put this on top of my rake task: task :task_name => :environment do

val_to_many
+1  A: 

rails 2:

Dir[Pathname(RAILS_ROOT) + 'app/models/**/*.rb'].each do |path|
  require path
end

rails 3:

Dir[Rails.root + 'app/models/**/*.rb'].each do |path|
  require path
end

another way:

(ActiveRecord::Base.connection.tables - %w[schema_migrations]).each do |table|
  table.classify.constantize rescue nil
end
tig
Problem with that is that, as noted in the question, that won't catch models added by plugins. In concrete terms, one of the important cases for the plugin I'm writing is a Spree shop, where basically none of the models are in `app/models`
scotchi
Just add `**/` at begining of glob => `Dir[Rails.root + '**/app/models/**/*.rb']`
tig
Though, why do you need to go through all models?
tig
It's a tool that basically build a graph out of all of the :has_many relationships, basically and then lets those be queried in interesting ways.
scotchi
Ok I added another way which uses tables (it will not load STI models)
tig
Note that `Rails.root` has been available in Rails 2 for quite a while.
John Topley
Do you know from which version I can use `Rails.root`?
tig
Not off the top of my head. Try it. If it works, then great and if it doesn't then use `RAILS_ROOT` instead.
John Topley