Ruby Nested Resources
When browsing the web lately have you noticed something similar with many sites’ URLs? The similarity that most of these URLs have is that it’s much easier for a regular person or even developer to understand what the site is trying to retrieve or show. This is called Restful Routing, which is an industry-standard to better organize routes. Let’s say you build an API to create a new author for your application, with restful routes the path would look something like this /authors/new, right away you know that this route has something to do with creating a new author and if you associate that route with its specific HTTP method, for example, GET ( GET /author/new ) you know that this is probably going get a form to create a new author. Now if you use POST (POST /author/new) you would be sending data to that route.
Restful Routes is a very important part of Ruby on Rails. Rails is all about the CRUD functionality and restful routes feel at home with Rails, so naturally, Rails has methods that will generate the routes for an object, one such method is called resources.
But let’s say you don’t need all those routes, and instead just one, you can use the :only or :except options and then by selecting the actions wish to or to not use.
As you can see the routes have the name of the object and then the symbol :id known as a dynamic segment. This symbol refers to the object’s id so that in your “show” action you can easily use the .find() method to find the correct user with that specific id. If we would like to view all the authors all we would have to do is just call /authors/ like and say we found the user with a specific id of 1 and we want to edit said user all we’d have to do is add “edit” to the route like so.
This works great if your site only has one object for our example an author, but we all know what authors are best at, and in this case, writing books for us to enjoy! By doing the same thing that we did for our authors, we will now do to our books. So now on our site, we can enter new Authors and also new books. And we can edit our book’s “new” view and “create” action so that if we are creating a new book we can easily assign the book to the author. But there is a much more restful way of doing so and this way is called Nested Routes.
Nested routes allow us to be able to capture the relationship in our routing very quickly and nicely. For example, let’s say we want to add a new book to our favorite author Mark Twain, instead of going straight to creating a book and then assigning it to Mark Twain we can easily go to Mark Twain’s profile and from there create the book, the book it will instantly be assigned to him because know in our actions we have access to an author’s id. Nested routes can be done easily by creating a resources block like so.

Now we are only able to edit and create books only if we have an author’s id. As you can see that our book’s edit and create routes have changed from /books/new to /authors/:author_id/books/new. This will also update our helper methods.


When using the newly created helper methods you will also have to pass an instance of both the author and book. This is also the case when creating a form with the form_for method that creates an object that is nested, in this case, our books resources “new” form will need to have an instance of a new book object and an author object


With nested resources, if we want to be able to create a new book for an author with an id of 3 all we have to do in our path is enter /authors/3/books/new which will send a GET request to render our book’s new view. This is also the same if we wanted to edit a book with an id of 5, /authors/3/books/5/edit. If we wanted to we could also nest more objects, for example, let's say we want to nest photos under our books resource, your path will start to look something similar to this /authors/3/books/5/photos/1/. As you can see having deeply nested resources will quickly become very cumbersome. Now you will have a new helper method called author_book_photo_path which will require you to specify objects at all three levels(author_book_photo_path(author_id, book_id, id)), this is why Resources should never be nested more than 1 level deep.
The only downside you might think is that you're probably going to be stuck showing an authors’ id and a book’s id as well, but that couldn't be any further from the truth. Thanks to the :param option that overrides the default resource identifier :id, you will be able to enter for example an author’s name and or a book's title in the path so it could like /authors/mark-twain/Adventures-of-Huckleberry-Finn. To accomplish this all that you would have to do is just add a new method containing the attribute of your choosing to the models you would like to change, for this example, it's our Book and Author models.


After we added the new to_param methods to our models all that is needed to be done is add the :param option to our resources. The only thing to keep account of is that you will no longer be able to use the .find() method to get the correct author or book but instead will have to use .find_by() and the .gsub() method.


It is very important that your routes easily explain what is happing that way users can if they wanted easily navigate to their preferred destination in the URL. This is also a plus for developers that might want to use your API quickly without having to constantly review any documentation.
Reference links:
https://edgeguides.rubyonrails.org/routing.html
https://www.learnhowtoprogram.com/c-and-net/basic-web-applications/introduction-to-restful-routing
https://github.com/learn-co-curriculum/routing-nested-resources-reading