Lucy Bain
Lucy Bain

Reputation: 2616

How can I write Rails 4 routing namespaces without duplicating the controller name?

What I'd like to be able to write is something like:

  namespace :cats do
    get '/:breed/' => '#search_by_breed'
    get '/:breed/count' => '#count_by_breed'
  end

But this leads to these routes:

  GET  /cats/:breed(.:format)       cats/#search_by_breed
  GET  /cats/:breed/count(.:format) cats/#count_by_breed

which, given the slash in cats/#show, won't work.

I know I can do this with the following:

  get '/:breed/' => 'cats#search_by_breed'
  get '/:breed/count' => 'cats#count_by_breed'

Which results in these routes:

   GET  /:breed(.:format)       cats#search_by_breed
   GET  /:breed/count(.:format) cats#count_by_breed

However, this duplicates naming the cats controller each time, which I'd rather not do (in my actual code I have more routes than just the two listed above. Unfortunately I'm not actually working on a cat search site...). I thought there'd be away around this.

Am I missing something? Just over doing the DRY commandment? It seems like this would be reasonably common, but I didn't find anything similar in the routing docs.

Upvotes: 2

Views: 434

Answers (1)

rossta
rossta

Reputation: 11494

To answer your primary question, this is one way to write your routes to accomplish what you want:

resources :cats, only: [], path: ":breed" do
  collection do
    get 'search_by_count', path: 'count'
    get 'search_by_breed', path: '/'
  end
end

This will generate the following routes:

search_by_count_cats GET    /:breed/count(.:format)  cats#search_by_count
search_by_breed_cats GET    /:breed(.:format)        cats#search_by_breed

Of course, you can still use a separate declaration of resources :cats to get the more RESTful versions of index, show, etc.

To answer your secondary question, "am I overdoing the DRY commandment?", that's largely a subjective matter. In my experience, I have seen many cases where we take DRY too far at the expense of readability and resulting in increased coupling. I personally find deciphering the following requires less mental overhead:

get '/:breed/'        => 'cats#search_by_breed'
get '/:breed/count'   => 'cats#count_by_breed'
get '/:breed/another' => 'cats#another_route'

For more thoughts on being sensible with DRY, I offer this article http://www.infoq.com/news/2012/05/DRY-code-duplication-coupling and this talk http://www.confreaks.com/videos/434-rubyconf2010-maintaining-balance-while-reducing-duplication

Upvotes: 2

Related Questions