After building Rails apps for some time, you eventually find yourself writing a lot of the same RESTful controller code over and over again. Some resources just require simple CRUD operations that follow similar patterns across apps. I’ve found myself copying and pasting code for CRUD operations from previous apps into new ones, making minor adjustments, so that I could get things up and running quickly. Thankfully though, there’s a better way: the inherited resources gem.
Inherited resources handles the common CRUD actions you’ve written a hundred times, and it’s quite easy to customize to your needs.
To get started, just add the inherited resources gem to your gemfile and run
Now let’s say we’ve got a Reddit-like forum application that has users, and users can make posts and comment on posts. Using inherited resources, you can set up your posts controller like this:
1 2 3 4 5 6 7 8
That’s it. Provided you declared
resources :posts in your routes file, the seven RESTful controller actions (index, new, create, show, edit, update and delete) are defined behind the scenes by inheriting from
InheritedResources::Base. Pretty nifty – a controller that would normally be at least 80 lines of code is reduced to just six!
Inherited resources also plays nicely with strong parameters. After you define your permitted parameters, they will automatically be used wherever
params would normally be called.
Working with associations
We need to customize our posts controller a little bit to ensure that each post created is associated with a specific user. Inherited resources provides simple ways to make these kind of customizations and maintain much cleaner controllers.
To associate all posts with the logged-in user, inherited resources provides a method
begin_of_association_chain that handles this nicely. Just add it as a protected method to the bottom of your posts controller:
1 2 3 4 5 6 7 8 9
I defined a
current_user helper method in my Application Controller that returns the
@current_user stored in the session. Now whenever I make a post, it’s automatically associated with that user. Magic.
For comments, we do something a little different. Let’s say we want user’s to be able to add comments right on the posts show page, and we’ll list all comments right underneath the post.
In my routes, I’ve nested comments under posts.
1 2 3
In my posts controller, I need to make sure I instantiate a comment object for the form on the posts show page. I accomplish this by simply adding this on top of the default post
1 2 3 4 5 6 7 8
And then I set up my comments controller like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
belongs_to :post? Not used to seeing that in a controller. This will ensure that each comment submitted is associated with the post that the user is viewing.
We’re not done with our comments controller though. By default, after a comment is created, the
create action will try to redirect to a show page for the specific comment. For our purposes though, we want to make sure that the user stays on the page of the post that he or she just commented on. This is easy to accomplish with inherited resource’s smart redirects, and it only takes adding the line
actions :create right underneath
1 2 3 4 5 6
actions :create tells the comment controller to redirect to the parent resource upon creation of the comment. Now I’ve got all the behavior I want for my simple forum application in a fraction of the code required to set up these actions.
Have fun with inherited resources
These are just a few quick examples of the power of the inherited resources gem. There are many more things you can do with it, such as ensure controller actions only respond with JSON for dynamically loaded content. All of this is nicely documented over at it’s GitHub page.
I’m just getting started with this gem and I’m excited to continue learning how it can slim out my controllers so that I can focus on more important things. It definitely provided a nice respite from the monotony of creating the same RESTful actions that I’ve written too many times to count among different projects.