I have two namespaces, each with its own controller and presenter classes:
Member::DocumentsController
Member::DocumentPresenter
Guest::DocumentsController
Guest::DocumentPresenter
Both presenters inherit from ::DocumentPresenter
.
Controllers access their respective presenters without namespace specified, e.g.:
class Guest::DocumentsController < ActionController::Base
def show
DocumentPresenter.new(find_document)
end
end
This usually calls presenter within same namespace. However sometimes in development environment I see base ::DocumentPresenter is being used.
I suspect the cause is that base ::DocumentPresenter is already loaded, so Rails class auto-loading doesn't bother to look further. Is this likely the case? Can it happen in production environment too?
I can think of two solutions:
Is there a better solution?
You are correct in your assumptions - If you do not specify namespace, Ruby starts from current namespace and works its way up to find the class, and because the namespaced class is not autoloaded yet, the ::DocumentPresenter
is found and autoloader does not trigger.
As a solution I would recommend renaming ::DocumentPresenter
to DocumentPresenterBase
, because this protects you from bugs when you forget namespacing or explicit requiring somewhere.
The second option to consider would actually be using specific namespaced classnames all over the place, but this suffers from bugs when you accidentally forget to namespace some call.
class Guest::DocumentsController < ActionController::Base
def show
Guest::DocumentPresenter.new(find_document)
end
end
Third option would be your second - explicitly require all the classes in initializer beforehand. I have done this with Rails API which receives embedded models in JSON
and Rails tends to namespace them when the actual models are not loaded yet.
Option 3.5 You could probably trick autoloader to do the heavy lifting (though, this might seem more like a hack):
class Guest::DocumentsController < ActionController::Base
# trigger autoload
Guest::DocumentPresenter
def show
# This should refer Guest::DocumentPresenter
DocumentPresenter.new(find_document)
end
def show
# As will this
DocumentPresenter.new(find_document)
end
end
Still the cleanest would be to rename the base class.
I think in 3 solutions if you want to mantein the name, one is your second solution.
1) explicitly require appropriate presenter files in controller files
2) Execute the full environment class path, like:
class Guest::DocumentsController < ActionController::Base
def show
Guest::DocumentPresenter.new(find_document)
end
end
3) Create a file on initialize directory and execute require manually (the worst options :S)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With