I'm sure this is some basic misunderstanding I have to how dependency resolution should work in Rails, but am experiencing some wierdness with modules and models.
I hadn't been using modules for models much because I had run into early issues with them, but woke up early this morning with the idea of a way to use them for something that we need.
This was in a brand new Rails 4.0 beta project (using github rails/rails master), but have the same behavior in Rails 3.2.6.
Here are the models. I just wanted to try to have the class load so I could see which class was being loaded, but just referencing these model classes causes issues:
app/models/associated_model.rb
class AssociatedModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}"
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
app/models/my_model.rb
class MyModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}"
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
app/models/root_only_model.rb
class RootOnlyModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}"
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
app/models/some_module/associated_model.rb
class SomeModule::AssociatedModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}" #bug
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
app/models/some_module/module_specific_model.rb
module SomeModule
class ModuleSpecificModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}"
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
end
app/models/some_module/my_model.rb
class SomeModule::MyModel < ActiveRecord::Base
puts "in #{
self.name}, AssociatedModel is #{AssociatedModel.name}"
puts "in #{
self.name}, ModuleSpecificModel is #{ModuleSpecificModel.name}"
puts "in #{
self.name}, MyModel is #{MyModel.name}"
puts "in #{
self.name}, RootOnlyModel is #{RootOnlyModel.name}"
end
And here is what happens in rails console:
$ rails c
Loading development environment (Rails 4.0.0.beta)
1.9.3p194 :001 > AssociatedModel
in AssociatedModel, AssociatedModel is AssociatedModel
NameError: uninitialized constant AssociatedModel::ModuleSpecificModel
from /path/to/new_rails_app/app/models/associated_model.rb:3:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/associated_model.rb:1:in `<top (required)>'
from (irb):1
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3p194 :002 > MyModel
in AssociatedModel, AssociatedModel is AssociatedModel
NameError: uninitialized constant AssociatedModel::ModuleSpecificModel
from /path/to/new_rails_app/app/models/associated_model.rb:3:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/associated_model.rb:1:in `<top (required)>'
from /path/to/new_rails_app/app/models/my_model.rb:2:in `<class:MyModel>'
from /path/to/new_rails_app/app/models/my_model.rb:1:in `<top (required)>'
from (irb):2
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3p194 :003 > RootOnlyModel
in AssociatedModel, AssociatedModel is AssociatedModel
NameError: uninitialized constant AssociatedModel::ModuleSpecificModel
from /path/to/new_rails_app/app/models/associated_model.rb:3:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/associated_model.rb:1:in `<top (required)>'
from /path/to/new_rails_app/app/models/root_only_model.rb:2:in `<class:RootOnlyModel>'
from /path/to/new_rails_app/app/models/root_only_model.rb:1:in `<top (required)>'
from (irb):3
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3p194 :004 > SomeModule::AssociatedModel
NameError: uninitialized constant SomeModule::AssociatedModel::AssociatedModel
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:2:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:1:in `<top (required)>'
from (irb):4
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3p194 :005 > SomeModule::ModuleSpecificModel
NameError: uninitialized constant SomeModule::AssociatedModel::AssociatedModel
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:2:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:1:in `<top (required)>'
from /path/to/new_rails_app/app/models/some_module/module_specific_model.rb:3:in `<class:ModuleSpecificModel>'
from /path/to/new_rails_app/app/models/some_module/module_specific_model.rb:2:in `<module:SomeModule>'
from /path/to/new_rails_app/app/models/some_module/module_specific_model.rb:1:in `<top (required)>'
from (irb):5
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3p194 :006 > SomeModule::MyModel
NameError: uninitialized constant SomeModule::AssociatedModel::AssociatedModel
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:2:in `<class:AssociatedModel>'
from /path/to/new_rails_app/app/models/some_module/associated_model.rb:1:in `<top (required)>'
from /path/to/new_rails_app/app/models/some_module/my_model.rb:2:in `<class:MyModel>'
from /path/to/new_rails_app/app/models/some_module/my_model.rb:1:in `<top (required)>'
from (irb):6
from /path/to/github/rails/railties/lib/rails/commands/console.rb:78:in `start'
from /path/to/github/rails/railties/lib/rails/commands/console.rb:9:in `start'
from /path/to/github/rails/railties/lib/rails/commands.rb:47:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Thanks in advance,
Gary