Teleolurian
6/18/2008 4:27:00 PM
On Jun 17, 9:50 pm, Bryan JJ Buckley <jjbuck...@gmail.com> wrote:
> Hi,
>
> Looks like you're trying to reinvent something that Rails already
> tries to do for you, and the two mechanisms aren't playing nicely
> together.
>
> 2008/6/18 Teleolurian <teleolur...@gmail.com>:
>
>
>
> > Background: I'm using ActiveRecord to handle some bulk uploads. I
> > decided it would be a good idea to put all my models into subfolders,
> > then load them with autoload [essentially, so I can namespace
> > everything into a module]. Here's the relevant code (i'm using
> > MODULENAMEBase.rb as the naming convention for the class that does
> > establish_connection):
>
> > module DBNamespace
> > def self.included(m)
> > @models_path = "models/#{m}"
> > require "#{@models_path}/#{m}Base.rb"
> > Dir.new(@models_path).entries.grep(/\.rb$/).collect do |fn|
> > cname = fn.sub(/\.rb$/, '')
> > cname[0] = cname[0].chr.upcase
> > m.autoload(cname, "#{@models_path}/#{fn}") unless fn ==
> > "#{m}Base.rb"
> > end
> > end
>
> > end
>
> > module PL
> > include DBNamespace
> > end
>
> > ----
> > Right now, I can check PL.autoload?(:Agent) and get the correct path;
> > I can even load the constant with PL.const_get(:Agent). However,
> > trying PL::Agent gives me a:
>
> > /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/
> > dependencies.rb:278:in `load_missing_constant': uninitialized constant
> > PL::Agent (NameError)
> > from /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/
> > active_support/dependencies.rb:467:in `const_missing'
>
> This happens because when you try to access PL::Agent directly, your
> PL module hasn't been explicitely included into anything, and
> therefore your `included` block was never called. Hence, no constant
> PL::Agent.
>
>
>
> > And doing an include PL; Agent gives me the odder:
>
> > /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/
> > dependencies.rb:252:in `load_missing_constant': Object is not missing
> > constant Agent! (ArgumentError)
> > from /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/
> > active_support/dependencies.rb:467:in `const_missing'
> > from /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/
> > active_support/dependencies.rb:479:in `const_missing'
> > from header.rb:7
>
> This is where you're tripping over Rails's ActiveSupport autoloading.
> First you include PL, which includes DBNamespace, and calls
> DBNamespace::included, and that terminates properly. At this point,
> you have added Agent as autoloadable... That would (probably) be fine
> in a pure Ruby application. But Rails already has an autoloading
> mechanism, which is based on overriding Class#const_missing, and which
> is apparently called as soon as you reference the (as yet unknown)
> constant Agent. This apparantly is already known (probably due to your
> manual addition of it to the autoload map).
>
>
>
> > Can anybody clear this up?
>
> I would recommend that if you want to namespace models like this, let
> Rails to the work its own way for you. Put files in a hierarchical
> structure under app/models or lib/ (which are both in the load path
> anyway), and name those files consistently. For example, in
> db_namespace.rb, just have
>
> Dir["#{File.basename(__FILE__, 'rb')}/**/*.rb"].each do |requirement|
> require requirement
> end
>
> and in db_namespace/agent.rb, do something like
>
> module DBNamespace
> class Agent
> # stuff
> end
> end
>
> Then Agent is autoloaded the first time ruby sees DBNamespace::Agent.
>
> Apologies if I've missed some of the point of what you were trying to
> do, but I do recommend that you stick to Rails conventions when doing
> something like this, as trying to second-guess all the ActiveSupport
> core extensions to Module and Class are almost guaranteed to cause
> headaches.
>
> --
> JJ
Thank you very much! Adding module namespaces around the model classes
was what I needed to do. Probably should have been obvious, but I've
just come back to ruby after a bit of a hiatus :)