Jutsu #2 – Single Table Inheritance with Rails 4 (Part 2)

Hi ! I’m finally back, sorry for the delay.

I sent my mémoire last week and I finally had some time to finish this article. Let’s continue our journey with Single Table Inheritance !

In this article, we are going to see how to create a common controller for our models (Animal, Lion, etc). We will also need to create the corresponding routes and add some helpers to generate the right paths. If you don’t have the code from the first part, you can get it here.

The common controller

Time to start working ! First, we have to generate the common controller for our models. The name is going to be AnimalsController which matches our parent model.

rails g controller AnimalsController index show new edit create update destroy

Define the routes

Let’s move to the routes file and define our routes. First, remove the lines generated by rails since we are going to use resources :

# Remove these lines from config/routes.rb
get "animals/index"
# Code hidden for brevity
get "animals/destroy"

Define the root of our app and the routes for Animals :

# config/routes.rb
Sti::Application.routes.draw do
 resources :animals
 root 'animals#index'

Setup the index action and the corresponding view

Fire up your server and access localhost:3000 and you will see, well nothing. We should add some content to our index view, maybe the list of all the animals in the database. To provide this list to the view, we need to add some simple code to our controller :

# app/controllers/animals_controller.rb
def index
  @animals = Animal.all

And copy/paste (or retype it, totally up to you) the following in animals/index.html.erb.

# app/views/animals/index.html.erb
<h1>The Lion Tribe</h1>
    <% @animals.each do |animal| %>
        <td><%= animal.name %></td>
        <td><%= animal.race %></td>
        <td><%= animal.age %></td>
        <td><%= link_to 'Show', "" %></td>
        <td><%= link_to 'Edit', "" %></td>
        <td><%= link_to 'Destroy', "", method: :delete, data: { confirm: 'Are you sure?' } %></td>
    <% end %>

The view still looks pretty bad huh, but whatever, it’s not a design tutorial. You are free to add some css (and you can even pull request on [the repo][2], I will definitely merge it if it looks good).

Now that we have a basic way to show our data, we can start playing with Single Table Inheritance. In the first part, we created one table animals and one model Animal. We also created 3 other models (Lion, Meerkat, WildBoars) that inherit from Animal and all live happily in the same table. Thanks to that, we avoided repeating code at the model level. We can follow the DRY rule at the controller level by using a unique controller for all our STI models.

Routes and STI

After a bit of code, the index action of the Animals controller will be able to show either all the animals or only the animals of a specific race. To do this, the controller need to know which race is requested. Thanks to Rails, we can define a default parameter in our routes.

# config/routes.rb
resources :animals
resources :lions, controller: 'animals', type: 'Lion' 
resources :meerkats, controller: 'animals', type: 'Meerkat' 
resources :wild_boars, controller: 'animals', type: 'WildBoar'

root 'animals#index'

See the type key ? That’s the trick. Everytime we access /lions/*, Rails will add a parameter in params with the key type. So, for each model that inherit from Animal, we define resource routes and specify that they have to use the animals controller. We also add the corresponding type.

We can now extract the type value in the controller with the following methods :

class AnimalsController < ApplicationController 
    before_action :set_race

    def index 
        @animals = Animal.all 

    # Code hidden for brivety


    def set_race 
       @race = race 

    def race 
        Animal.races.include?(params[:type]) ? params[:type] : "Animal"

    def race_class 


Basically, before any action we assign the value of the race params, or Animal if no race is passed, to the variable @race so our views can access it. We can now change the Animal.all to race_class.all. The method race_class is going to send back the constantized parameter type like Lion for example.

def index
  @animals = race_class.all

Warm Up

If you access http://localhost:3000, you will have the list of all animals. But if you access http://localhost:3000/lions or http://localhost:3000/meerkats, you only get the list of the specified animal. Wonderful, isn’t it ?!

That’s it for this article. In the next part, we are going to add dynamic paths and the missing views !

Related articles

Do you want more awesome tutorials?

Subscribe to my newsletter to receive them directly in your mailbox. You will also get a free chapter from my book!



I'm Thibault, a Ruby on Rails developer based in Bangkok! I love clean Ruby code and easy to follow Rails tutorials. I hope you'll find what you're looking for on Samurails!

12 thoughts on “Jutsu #2 – Single Table Inheritance with Rails 4 (Part 2)

  1. Hi

    Excellent tutorial! It has been very useful to me.

    I have trying to fix some problems when I was following the tutorial and I end in this question at StackOverflow (link) where they point that just constantize the type coming from params is insecure (you’ll parse anything coming in type).

    So, maybe it will convenient to modify the race_class method to

    def race_classes
    ['Animal', 'Lion', 'Meerkat', 'WildBoar']

    def race_class
    type.constantize if type.in? race_classes



    1. Hi David,

      That’s a very good point, I will update the code ASAP !
      It is indeed very insecure to blindly parse data coming from the client.

      Thanks for letting me know ;)


  2. I keep getting this error from the index view:
    The single-table inheritance mechanism failed to locate the subclass: ‘WildBoar’. This error is raised because the column ‘race’ is reserved for storing the class in case of inheritance.

    I don’t understand, I already subclassed WildBoar to the Animal class.

    My repo can be found here: https://github.com/alvinkatojr/sti

  3. One quick note (don’t get me wrong I’m not trying to be a smartass) you forgot to mention that you have a class method races in the Animal model which returns an array with the names of the models that inherit from the Animal model

      1. btw much thanks for the great tutorial, I’ve enjoyed reading it. As a guy which is new to Rails I’ve learned some new tricks besides the STI that I actually came for :)

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>