T
We're Happier Together! NYC Devshop has joined the HappyFunCorp family! Learn more!

Devshop

Using Inherited Resources

Using Inherited Resources

Development

Using Inherited Resources

Posted by: Jared Rader

Friday, Jun 20th, 2014

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 `bundle install`.

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:

class PostsController < InheritedResources::Base

private
def post_params
params.require(:post).permit(:title, :content)
end
end

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:

class PostsController < InheritedResources::Base

# ...
protected
def begin_of_association_chain
current_user
end
end

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.

resources :posts do

resources :comments, only: [:create, :destroy]
end

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 `show` action:

class PostsController < InheritedResources::Base

def show
@comment = resource.comments.build
super
end
# ....
end

And then I set up my comments controller like this:

class CommentsController < InheritedResources::Base

belongs_to :post
private
def comment_params
params.require(:comment).permit(:content)
end
protected
def begin_of_association_chain
current_user
end
end

Notice the `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 `belongs_to :post`:

class CommentsController < InheritedResources::Base

belongs_to :post
actions :create
#...
end

The line `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.

Devshop

About Us

Devshop is a highly motivated group of entrepreneurs, developers, and designers that aim to work with companies that are looking for an edge. Each member of our team brings something unique to the table allowing us to cater our services specifically to meet your needs and exceed your expectations.