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