Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    [Rails] Single Table Inheritance

    Published Jun 05, 2022 [  Ruby  ]

    Sometimes, you may want to share fields and behavior between different models. Let’s say we have Car, Motorcycle, and Bicycle models. We will want to share the color and price fields and some methods for all of them, but having some specific behavior for each, and separated controllers too.

    First, let’s generate the base Vehicle model:

    bin/rails generate model vehicle type:string color:string price:decimal{10.2}
    

    Did you note we are adding a “type” field? Since all models will be saved in a single database table, Rails will save in this column the name of the model that is being saved. In our example, this can be “Car”, “Motorcycle” or “Bicycle.” STI won’t work without a “type” field in the table.

    Next, we will generate the Car model that inherits from Vehicle. For this, we can use the --parent=PARENT option, which will generate a model that inherits from the specified parent and without equivalent migration (since the table already exists).

    For example, to generate the Car model:

    bin/rails generate model car --parent=Vehicle
    

    The generated model will look like this:

    class Car < Vehicle
    end
    

    This means that all behavior added to Vehicle is available for Car too, as associations, public methods, etc.

    Creating a car will save it in the vehicles table with “Car” as the type field:

    INSERT INTO "vehicles" ("type", "color", "price") VALUES ('Car', 'Red', 10000)
    

    Querying car records will search only for vehicles that are cars:

    Car.all
    

    will run a query like:

    SELECT "vehicles".* FROM "vehicles" WHERE "vehicles"."type" IN ('Car')
    

    Reference