Dependency loading confusion

Hey guys,

I have a module Foo::Bar, which extends ActiveRecord::Base with some
custom functionality. This module is in lib/foo/bar.rb. Inside this
file is also the code, that includes the module into
ActiveRecord::Base:

module Foo
  module Bar
    # stuff ...
  end
end

ActiveRecord::Base.send(:include, Foo::Bar)

Then, this file is required in config/initializers/foo.rb:

require 'foo/bar'

The problem is, that sometimes i get this nasty error:

A copy of Foo::Bar has been removed from the module tree but is

still active!

and I really can’t figure out what’s the problem. The weird thing is
that the error disappears when I restart the application, but
sometimes appears again on a different page. It looks completely
magical to me :slight_smile:

Everything works fine in test and production environments, so this has
probably something to do with the Rails dependency loading/unloading
magic.

So, I guess I can make it into a plugin, but it’s really very simple
and quite specific to my application, so it’s not worth the effort.
That’s why I want to keep it only in lib.

Things I tried:

  • Putting the lib/foo path into config.load_once_paths in config/
    environment.rb
  • adding unloadable to the Foo::Base module
  • moving the include line (ActiveRecord::Base.send(:include, …) into
    config/initializers/foo.rb

But nothing helps :frowning:

Any help will be appreciated. Thanks.

adam.

On Mar 1, 12:12 pm, Adam Cigánek [email protected] wrote:

  end
A copy of Foo::Bar has been removed from the module tree but is

still active!

and I really can’t figure out what’s the problem. The weird thing is
that the error disappears when I restart the application, but
sometimes appears again on a different page. It looks completely
magical to me :slight_smile:

What happens is that your app loads and serves the first request fine.
Then rails unloads unloadable code. When the next request arrives,
ActiveRecord::Base, which isn’t reloadable now has the dead module
included. Only development uses this way of loading classes

  • Putting the lib/foo path into config.load_once_paths in config/
    environment.rb

This should work. You do (if my memory is correct) need to use
absolute paths though - check what’s already in
ActiveSupport::Dependencies.load_once_paths

Fred

Thanks for the reply Fred.

This should work. You do (if my memory is correct) need to use
absolute paths though - check what’s already in
ActiveSupport::Dependencies.load_once_paths

It doesn’t :frowning: I checked the content of
ActiveSupport::Dependencies.load_once_paths and the lib/foo is there
and it’s an absolute path. It is first element of the list, all the
others are plugins and gems paths. Not sure if I’m doing it correctly,
but I put this into the Rails::Initializer.run { … } block in the
config/environment.rb:

config.load_only_paths << "#{Rails.root}/lib/foo"

just after I define all gem dependencies.

Am I doing it right?

adam.

Ah, don’t forget to do require_dependency rather than require (or
else you’re half bypassing the rails dependency system and odd things
can happen). Worth also sticking some breakpoints in AS::Dependencies
to check that your file is being handled properly.

Hey, that was it! Ok, now I understand the dependency loading voodoo
little bit better :slight_smile: Thanks Fred.

adam.

On Mar 1, 2:55 pm, Adam Cigánek [email protected] wrote:

config.load_only_paths << "#{Rails.root}/lib/foo"

just after I define all gem dependencies.

Ah, don’t forget to do require_dependency rather than require (or
else you’re half bypassing the rails dependency system and odd things
can happen). Worth also sticking some breakpoints in AS::Dependencies
to check that your file is being handled properly.

Fred