Search code examples
ruby-on-railsroutesnested-routes

What are nested routes for in Rails?


I am new to learning Rails and have just encountered nested routes. The example I am looking at involves blog articles and comments. I am trying to undestand what the benefit of nested routes are in Rails.

As far as I can tell all the information contained in a nested route for a comment such as /articles/:article_id/comments/:id(.:format) is all contained in the comment object itself so it does not communicating additional information to the Action.

Why not just have unnested routes such as /comments/:id(.:format)?

There is obviously a very good reason for using nested routes but I havent been able to work it out. The only benefit I can see so far is it gives a better illustration of the relation between articles and comments when reading the URL but all this information is contained in the comment object anyway.

Could someone explain this?


Solution

  • In your model you would have setup this association

    class Article< ActiveRecord::Base
      has_many :comments
    end
    
    class Comment< ActiveRecord::Base
      belongs_to :article
    end
    

    So each comment is associated with an article and you need some logic to find corresponding article for a comment

    This is where nested route comes in and lets you find article for that comment in your controller action. If you look at that route again

    /articles/:article_id/comments/:id(.:format)
    

    This is the comment controllers show action and this route allows you to find both article and your comment inside show action

    def show
      @article = Article.find(params[:article_id])
      @comment = Comment.find(params[:id])
      # if you are not using nested routes then you can find out associated article by
      @article = @comment.article # but you'll have to query your database to get it which you can simply find if you are using nested route
    end
    

    More than the show action(where you can use some other logic to find article associated with that comment) you need nested route for your new action where you have to find that article and then build a comment for that article by something like

    def new
      @article = Article.new
      @comment = @article.comments.build
    end
    

    As @August pointed out you can separate out actions for which you want your route to be nested by using shallow nesting, you can do:

    resources :articles do
      resources :comments, shallow: true
    end
    

    Checkout nested routes for more information