Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails nested resources and routing - how to break up controllers?

Tags:

I have the following models:

  • Post
  • Tag
  • TaggedPost (from which Post and Tag derive their associations by has_many :through)

And I have the following routes.rb file:

resources :tags  resources :posts do   resources :tags end 

So when I navigate to, say, /posts/4/tags, that will shoot me into the index action for the Tag controller with the post_id value set in the parameters array. Cool.

My question is though, now that I'm accessing the nested tags resource under posts, should I be hitting the Tags controller still? Or should I setup some other controller to handle the nested nature of tags at this point? Otherwise I have to build additional logic into the Tags controller. This can be done of course, but is this the common way of handling nested routes and resources? The code I have in the index action for the Tags controller is as follows:

TagsController.rb

def index   if params[:post_id] && @post = Post.find_by_id(params[:post_id])     @tags = Post.find_by_id(params[:post_id]).tags   else     @tags = Tag.order(:name)   end   respond_to do |format|     format.html     format.json {render json: @tags.tokens(params[:q]) }   end end 

I can see the code in this controller growing increasingly large, as I plan for many additional resources to be associated with tag resources. Thoughts on how to break this out?

Summary of questions:

  1. If a resource is nested, should the nested resource be going through a different controller representing the nested nature of the resource? This is opposed to going through the normal controller as I am in the code example that I provided.
  2. If so, how should these controllers be named and setup?

Let me know if you need more information.

like image 868
Lester Peabody Avatar asked Feb 18 '13 21:02

Lester Peabody


People also ask

What are the 7 CRUD routes generated by the resources Method resources songs in Rails?

In Rails, there are seven standard CRUD actions: index, show, new, create, edit, update, and destroy, which relate to specific HTTP verbs and are usually implemented using specific ActiveRecord methods.

What is the difference between resources and resource in Rails?

Difference between singular resource and resources in Rails routes. So far, we have been using resources to declare a resource. Rails also lets us declare a singular version of it using resource. Rails recommends us to use singular resource when we do not have an identifier.

How do I create a nested route in Rails?

In a nested route, the belongs_to (child) association is always nested under the has_many (parent) association. The first step is to add the nested routes like so: In the above Rails router example, the 'index' and 'show' routes are the only nested routes listed (additional or other resources can be added).

What does resources do in Rails routes?

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. A single call to resources can declare all of the necessary routes for your index , show , new , edit , create , update , and destroy actions.


2 Answers

I think the best solution is to split up controllers:

    resources :tags      resources :posts do       resources :tags, controller: 'post_tags'     end 

And then you have 3 controllers. Optionally, you can inherit PostTagsController from TagsController to do something like:

    class PostTagsController < TagsController         def index             @tags = Post.find(params[:post_id]).tags             super         end     end 

If the difference is only the retrieval of tags, you can:

    class TagsController < ApplicationController         def tags             Tag.all         end          def tag             tags.find params[:id]         end          def index             @tags = tags             # ...         end         # ...     end      class PostTagsController < TagsController         def tags             Product.find(params[:product_id]).tags         end     end 

Use that methods and simply override tags in the inheriting controllers ;)

like image 196
Iazel Avatar answered Sep 27 '22 19:09

Iazel


All you are doing with nested resources is changing the routing URL. Only thing you would have to do is make sure you are passing the proper id (in your case post)to the tag controller. Most common error is the Can't Find *** ID.

If you don't nest a profile route into a user route it would look like this

domain.com/user/1

domain.com/profile/2

When you nest the routes it would be

domain.com/user/1/profile/2

That is all that it is doing and nothing else. You don't need additional controllers. Doing nested routing is just for looks. allowing your user to follow the association. The most important thing about nesting routes is that you make sure you make the link_to's to the right path.

When not nested: it would be

 user_path 

and

 profile_path 

when it is nested you would need to use

user_profile_path 

rake routes is your friend to find out how the routes have changed.

Hope it helps.

like image 24
Richard Lau Avatar answered Sep 27 '22 20:09

Richard Lau