Chris Remst
Chris Remst

Reputation: 41

Routing for self-referencing association in Rails 4

I am attempting to set up a route for a self-referencing nested association. The goal is to get a URL of /category_name/subcategory_name.

I'm using friendly_urls to get the category names instead of IDs. I've been able to get half of it to work with this:

match '/:id' => 'listing#index', :via => 'get', as: 'category'

However, everything I try to get the subcategory to work is failing? The only answers I've come across are to create another model/controller for the subcategories. If possible, I'd like to avoid that as it'll add extra complexity for little gain. I wouldn't really need any of the extra methods/flexibility that separate methods might provide.

This is my first Rails app so please excuse the basic nature of this question.

Upvotes: 0

Views: 652

Answers (2)

Alejandro Babio
Alejandro Babio

Reputation: 5229

If I were you, I make this way:

Define routes:

resources :categories do
  resources :categories, path: '/'
end

Which rake routes show:

   category_categories GET    /categories/:category_id(.:format)          categories#index
                       POST   /categories/:category_id(.:format)          categories#create
 new_category_category GET    /categories/:category_id/new(.:format)      categories#new
edit_category_category GET    /categories/:category_id/:id/edit(.:format) categories#edit
     category_category GET    /categories/:category_id/:id(.:format)      categories#show
                       PATCH  /categories/:category_id/:id(.:format)      categories#update
                       PUT    /categories/:category_id/:id(.:format)      categories#update
                       DELETE /categories/:category_id/:id(.:format)      categories#destroy
            categories GET    /categories(.:format)                       categories#index
                       POST   /categories(.:format)                       categories#create
          new_category GET    /categories/new(.:format)                   categories#new
         edit_category GET    /categories/:id/edit(.:format)              categories#edit
              category GET    /categories/:id(.:format)                   categories#show
                       PATCH  /categories/:id(.:format)                   categories#update
                       PUT    /categories/:id(.:format)                   categories#update
                       DELETE /categories/:id(.:format)                   categories#destroy

On the categories_controller you can identify a nested category (subcategory) because params[:category_id] is not nil. And if it is nil the action is for a parent category.

Edit Added path option.

I think you want this:

   category_categories GET    /:category_id(.:format)          categories#index
                       POST   /:category_id(.:format)          categories#create
 new_category_category GET    /:category_id/new(.:format)      categories#new
edit_category_category GET    /:category_id/:id/edit(.:format) categories#edit
     category_category GET    /:category_id/:id(.:format)      categories#show
                       PATCH  /:category_id/:id(.:format)      categories#update
                       PUT    /:category_id/:id(.:format)      categories#update
                       DELETE /:category_id/:id(.:format)      categories#destroy
            categories GET    /                                categories#index
                       POST   /                                categories#create
          new_category GET    /new(.:format)                   categories#new
         edit_category GET    /:id/edit(.:format)              categories#edit
              category GET    /:id(.:format)                   categories#show
                       PATCH  /:id(.:format)                   categories#update
                       PUT    /:id(.:format)                   categories#update
                       DELETE /:id(.:format)                   categories#destroy

you must do the same on the outer route:

resources :categories, path: '/' do
  resources :categories, path: '/'
end

Upvotes: 3

craig.kaminsky
craig.kaminsky

Reputation: 5598

Without seeing your routes file or definitively knowing the name of your controller (listing should probably be listings since Rails controllers are typically plural, unless of course you consciously named your controller listing).

Assuming the controller is listings and you want to pass in category names and subcategory names to that controllers index method, I would make my match|get route the following:

get '/:category_name/:subcategory_name', to: 'listings#index', as: 'category'

Then, in the index method of the ListingsController, I could potentially (assuming they're provided) check for params[:category_name] and params[:subcategory_name] and act on them accordingly.

The Rails Routing guide is pretty helpful, too.

Upvotes: 0

Related Questions