📜 ⬆️ ⬇️

STI - one table and many models.

Yesterday, in a note about polymorphic links in the comments the STI pattern was mentioned. As it turned out, not everyone knows what it is, how it works and why it is needed. I decided to fill this informational gap and briefly tell about this design pattern and its implementation in Rail.

STI (Single Table Inheritance) is a design pattern that allows you to transfer object-oriented inheritance to a relational database table. In the database table there should be a field identifying the name of the class in the hierarchy. Often, including in RoR, the field is called type.

Thus, we can have one table and several types of objects (models) that will be stored in it. In the case of the aforementioned habrasame, this is one post table that stores posts of different types: link, podcast, article, translation, etc.
')
In order not to complicate your life, in this article we will consider a simpler example: several types of users with different powers and any other business logic. Let it be: administrator, manager and ordinary user.

Let's get started

Deciding on a task


For example, in our application (for example, an online store) we need to implement a hierarchy of users with different powers and, possibly, additional logic. Let it be: administrator, manager and ordinary user. It is logical for everyone to create a separate model: Administrator, Manager, User. All user accounts are stored in the same database table.

Create a database structure


We need one table, for the sake of maximum simplification there will be two fields in it: username and password . Also, we need to somehow store the user type, the default in the Rail for this purpose is a field called type .

As a result, we obtain the following structure:
CREATE TABLE users ( <br> id INT NOT NULL AUTO_INCREMENT , <br> username VARCHAR ( 20 ) NOT NULL UNIQUE , <br> password VARCHAR ( 32 ) NOT NULL , <br> type VARCHAR ( 40 ) NOT NULL , <br> PRIMARY KEY ( id ) <br> ) ;

Of course, it would be better to write a migration, but this is already beyond the scope of this article. We will consider this a task for independent work :)

We create models


Create an ordinary user model:
class User < ActiveRecord::Base <br> end

It should be borne in mind: we do not explicitly indicate the name of the table for this model. in this case, the name of the table and model are consistent with the conventions adopted in the Rail.

Create a model manager, inherit from the base user:
class Manager < User<br> end

Create an administrator model, inherit from the manager:
class Administrator < Manager<br> end

To simplify the example, we do not complicate the model with additional logic that we would need in a real application. If required, you can always add a specific code for each type of user to the appropriate model.

We use!


Now in the controller we can make samples from models in the usual way:
users = User. find ( :all )
In this case, we will get all users, including ordinary, managers and administrators.

But if we make a selection from the Administrator model, we will get only administrators:
administrators = Administrator. find ( :all )

Instead of conclusion


In this article, we missed many aspects that are not directly related to the main topic from writing migrations to using generators. Also, not all the features that are provided by Rail ActiveRecord when using STI are mentioned. Those interested can explore these points on their own.

Single Table Inheritance by Martin Fowler
ActiveRecord documentation in Ruby on Rails

Source: https://habr.com/ru/post/79630/


All Articles