creating a model registry

Hi all,

This is a problem I've approached so many times and always worked
around, that now I want to solve it once and for all. Say I have
something like this:

I. E. Smith-Heisters wrote:

---
class X < ActiveRecord::Base
  acts_as_wacky
end

module Wackinator
  class ControlAllWackos
    @@wackos = []
    def self.kill_wackos
      @@wackos.each(&:kill)
    end
  end

  def acts_as_wacky
    ControlAllWackos.wackos << self
    # do stuff
  end
end
---

require 'wackinator'
class X < ActiveRecord::Base

hth

ilan

I. E. Smith-Heisters wrote:

>
> ---
> class X < ActiveRecord::Base
> acts_as_wacky
> end
>
> module Wackinator
> class ControlAllWackos
> @@wackos = []
> def self.kill_wackos
> @@wackos.each(&:kill)
> end
> end
>
> def acts_as_wacky
> ControlAllWackos.wackos << self
> # do stuff
> end
> end
> ---
>

require 'wackinator'
class X < ActiveRecord::Base

hth

ilan

But that code won't be evaluated until the model X is used somewhere,
which is totally indeterminate. So if you boot your app and right away
call Wackinator::ControlAllWackos.kill_wackos, chances are X *hasn't*
been loaded and @@wackos will be empty. Or am I missing something?

Thanks,
Ian

What about using the Dir.glob trick only through initializers for
production.rb?

Hm, yes... but then you can't test your code. Given that choice, I'd
rather have a hard-to-maintain static list. Perhaps if I look further
into *why* things don't work in development I can find a way of fixing
it. But that still wouldn't address the possibility of there being a
model defined somewhere else than app/models, which I guess is a
sufficiently rare case to ignore.

Ok, looking into cache_classes led me to this solution, which seems to work:

in config/environment.rb:

silence_warnings do
  Dir.glob(File.join(RAILS_ROOT, 'app', 'models',
'*.rb')).each{|m|require_or_load m}
end

elsewhere:

module Wackinator
class ControlAllWackos
   @@wackos = []
   def self.kill_wackos
     @@wackos.each(&:kill)
   end
end

def acts_as_wacky
   ControlAllWackos.wackos << self
   # do stuff
end
end

The important part is that you have to use require_or_load instead of
require so that eagerly loading all the models works in development
mode. From there you can do whatever you want, in my case I'm
registering all my wackos so that they're available in
ControlAllWackos.wackos.

Work for me at the moment...

-Ian

Very interesting... thanks for the follow up.