There once was a project that made extensive use of Pivotal's "Unbuilt Rails Dependency" pseudo-Gem architectural feature. After realising that that was far more limited in its applicable use cases than hoped, efforts were made to claw those back into namespaced classes within the main Rails app.
This was generally successful for a while. The use-case actions/service layer and one of the two core entities, User
s, worked Just Fine. When work began on the Post
entity, however, increasing forward progress was abruptly halted by a weird error.
Given the files spec/entities/post_spec.rb
and app/entities/post.rb
as below, running bundle exec rspec spec/entities/post_spec.rb
gives the following output
Coverage report generated for RSpec to /Users/jeffdickey/src/rails/meldd/new_poc/coverage. 377 / 707 LOC (53.32%) covered.
Coverage = 53.32%. Sending report to https://codeclimate.com for branch post-entities... done.
/Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:495:in `load_missing_constant': Unable to autoload constant Post, expected /Users/jeffdickey/src/rails/meldd/new_poc/app/entities/post.rb to define it (LoadError)
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:184:in `const_missing'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:526:in `load_missing_constant'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:184:in `const_missing'
from /Users/jeffdickey/src/rails/meldd/new_poc/spec/entities/post_spec.rb:5:in `<module:Entity>'
from /Users/jeffdickey/src/rails/meldd/new_poc/spec/entities/post_spec.rb:4:in `<top (required)>'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `load'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `block in load_spec_files'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1224:in `each'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1224:in `load_spec_files'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:97:in `setup'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:85:in `run'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:70:in `run'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/runner.rb:38:in `invoke'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/gems/rspec-core-3.2.2/exe/rspec:4:in `<top (required)>'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/bin/rspec:23:in `load'
from /Users/jeffdickey/src/rails/meldd/new_poc/vendor/ruby/2.2.0/bin/rspec:23:in `<main>'
Bear in mind that Post
is the second entity to be given this treatment. There is a corresponding Entity::User
entity that Works Just Fine, including running its top-level RSpec specs as bundle exec rspec spec/entities/user_spec.rb
.
As i describe in a comment below. Major thanks to @bradstewart
for his patient prodding that finally "[knocked] my mental rust loose".
I'm just gonna start guessing. As you stated, Rails autoloads everything in subdirectories of
app
. But it expects the constants defined in those subdirectories to be top level; e.g.app/models
defines classes likeUser
notModel::User
. So Rails goes off looking forPost
in its autoload paths which it doesn't find because that doesn't actually exist,Entity::Post
does.and
Are not identical, they lookup constants differently. I'm guesing
post_spec.rb
goes looking for plain oldPost
which doesn't exist in an autoload path whileuser_spec.rb
goes looking forEntity::User
which exists in the autoload paths. I think it would pick it up correctly ifEntity::Post
were defined inapp/entities/entity/post.rb
.