controllers in sub-directories without namespaces?

Hello all

As I adopt REST more and more, my app has grown to have a lot of nested routes - only nested one level deep - that are starting to get a bit cumbersome to manage. e.g.

resources :products do   resource :promotion   resource :discount   # etc end

each nested resource has it's own controller. I'd like to group to controllers so I used the :module option on each nested resource and created a namespaced controller. e.g.

resources :products do   resource :discount, :module => :product end

This works fine, and the controller happily lives under controllers/ product/discounts_controller.rb

However, a few of the libraries and gems I use don't cope so well with namespaces, especially when the associated model isn't also namespaced. To get around this, I've added 'app/controllers/products' as a load path in environment.rb and I've also added that path to the view paths for relevant (nested) controllers.

This has worked great so far and I my tests are passing. I was just wondering if anyone would caution against this approach? I'm generally quite cautious about changing defaults and expected conventions!

many thanks John

Hello,

Nested routes are for prettier urls and better leaner controllers. If you need to scope the controller based on what it is nested under its not DRY code.

Why are you doing it this way? What is the problem you are trying to overcome.

Brian

I'm not sure I understand what you mean by not DRY. Here is how my controller directory looks without namespaces/sub-directories:

app/controllers/products_controller.rb app/controllers/discounts_controller.rb app/controllers/promotions_controller.rb . . app/controllers/expirations_controller.rb app/controllers/coupons_controller.rb

apart from products controller, each of the controllers listed manages a resource with some relation to the Product model. Either it's an associated model (Coupon) or it's a resource that manipulates Product in some way (e.g. products/14/expirations/create calls @prouduct.expire!). Each resource needs to load the associated parent for things like authorisation, so I think a parent/child setup is valid.

previously, 'discount', 'promote', 'expire' etc were all extra actions in the products controller. They now have their own controllers, but I have 60+ controllers each handling different resources. As you can imagine, this is making the controllers directory a little unwieldy and I'm looking for a way to better organise the controllers to make them easier to find. In the case of nested resources, grouping by the name of the parent resource seems like a logical approach.

How is scoping based on the parent any less DRY than having no scope?

John,

I read your post as you had, for example, multiple promotion controllers based on what it was a promotion for.

So your question is how to better organize your code/app/resources so you don't have so many controllers? Each controller generally only one parent object that it is attached to?

Since it looks like your making a storefront I would suggest looking at Spree's ERD for inspiration. (http://rails-erd.rubyforge.org/images/ spree.png)

To answer your original question about load paths, no gems should be explicitly requiring a file from the app directory. Of course some of them may, but they should rely on the rails magic to find the necessary model (and presumable controller) files if they need them.

Hello all

As I adopt REST more and more, my app has grown to have a lot of

nested routes - only nested one level deep - that are starting to get

a bit cumbersome to manage. e.g.

resources :products do

resource :promotion

resource :discount

etc

end

each nested resource has it’s own controller. I’d like to group to

controllers so I used the :module option on each nested resource and

created a namespaced controller. e.g.

resources :products do

resource :discount, :module => :product

end

This works fine, and the controller happily lives under controllers/

product/discounts_controller.rb

However, a few of the libraries and gems I use don’t cope so well with

namespaces, especially when the associated model isn’t also

namespaced. To get around this, I’ve added ‘app/controllers/products’

as a load path in environment.rb and I’ve also added that path to the

view paths for relevant (nested) controllers.

Any chance you’d be willing to list some of the gems that aren’t working with your setup? It might be in yours and everyones best interest to try to fix get the gems themselves fixed so they can properly work with nested controllers and nested models.

This has worked great so far and I my tests are passing. I was just

wondering if anyone would caution against this approach? I’m

generally quite cautious about changing defaults and expected

conventions!

If it is working for you (your tests are passing after all) then I’d just go with your current solution (modifying the load path, etc) until the gems you depend on can be fixed. Those who better know rails internals may wish to comment, however, on future problems you may or may not have.

Either way, I’d treat your current solution as a temporary fix and try to fix the gems you rely on (most gem authors would welcome a patch/pull-request if it’s clean and includes tests). I may be biased though since I was once frustrated by issues that arose from using nested models and controllers waaaay back in the rails 2 days… I just think nesting ought to work and be supported/correctly-implemented across the rails landscape. My $0.02

Brian, both Spree and ERD are very helpful. I hadn't come across them before. Thanks!

That's a great suggestion, I'll post tickets on the various issue trackers and summarise them here later.