This is probably caused by rails' autoloader. When doing this :
module Foo
class Bar
end
end
And then trying to use Foo::Bar
, the autoloader first tries to locate app/models/foo/bar.rb
. The file is loaded, and module Foo
is defined here (albeit as a module containing solely Bar
) so the autoloader never attempts to load app/models/foo.rb
.
This should only happen in development mode, as in production mode all of your files are require
'd on startup.
There are two workarounds AFAIK :
Cheat the autoloader
declare your class using class Foo::Bar
, to force the autoloader to resolve a constant lookup for Foo
.
This has the annoying side effect that the constant lookup inside Bar
will NOT be scoped inside Foo
, for instance :
# app/models/foo.rb
module Foo
BAZ = "baz"
end
# app/models/foo/bar.rb
class Foo::Bar
def baz
BAZ
end
end
here, Foo::Bar.new.baz
will fail, unless you reference the constant using Foo::BAZ
. This can get really a mess when defining ActiveRecord associations, for instance.
Require the module
using require_dependency
:
require_dependency 'foo'
module Foo
class Bar
end
end
This is IMHO the right solution, as it does not break the constant lookup, but it is also a bit annoying as you have to add the require statement on top of each namespaced file.
Note :
This bug seems to have been resolved in rails 4. I used the second workaround a lot while on rails 3, but I've tried to reproduce the bug in rails 4 and it does not show up anymore. I think they modified the way the autoloader works... For more info, see the rails guides on autoloading and reloading constants
require 'repsys.rb'
inmodels/foo/setting.rb
. Seems like Rails doesn't loadfoo.rb
if I am accessingFoo::Settings
. If requiring is the only solution that would be pretty poor! – Bombazine