Surely, many people face a problem when there are several models, say, Client, Manager and User - which have a number of fields - for example, name, email, position - the same. In addition, each of the models also has unique fields and methods. In this case (arguing abstractly), it would be logical to put the common fields with the corresponding validations in a separate table of people (Person model), leaving only specificity in Client, Manager and User.
A number of examples can be continued: Product - Fridge, Phone, Toaster; Vehicle - Car, Truck, Motorcycle and so on. The problem is pretty general - what solutions are there for Rails?
Options
Single Table Inheritance (STI)
Much has been written about this, in particular in the
Rails Guides and on Habré
here and
here . The bottom line is that we put the records for Client, Manager, and User in the same people table, using the special type field to make it clear who is who. Here is an example; it is conditional, common fields are marked with an asterisk, private fields are marked with capital letters of model names:
type | name* | email* | position (M) | company (C) | hobby (U)
However, in this case, the Manager acquires the unusual property of hobby from User. Also, the field of hobby managers will always be empty. User, Client and Manager in this case are subclasses of Person that do not have their own tables, and each unique property must be declared in the parent table / model.
')
In principle, it would be possible to close our eyes to this, but what if the Manager requires the creation of 42 own fields that have nothing to do with Client and User? In this case, it would be more logical to transfer specific fields to separate tables clients, managers, leaving only common fields in people, as well as type and id to build the necessary connections. Such a scheme, as Google suggests, is called Multiple Table Inheritance, but, unfortunately, Rails does not yet know anything about it, and, as a quick search in the developer forum shows, is not going to be in the foreseeable future.
Nested attributes + Delegation
The problem can be solved like this:
class Manager < ActiveRecord::Base belongs_to :person
In principle, it’s an option, but in this case you’ll have to allocate the general attributes all the time to a separate hash when creating or modifying a record, as well as using the fields_for helper when displaying forms, and also doing additional squats in the controller and model, which is
detailed in the same Rails Guides.
I would also like a "seamless" merge between both models and complete isolation of the particulars of the implementation of the common fields Manager, User and Client from the point of view of other application classes.
Your garden
For obvious reasons, I don’t want to fence it at all, although if you search for a combination of “rails multiple table inheritance” or “rails class table inheritance”, then there are many options for implementing your own MTI.
Gems
From the very beginning it was logical to assume that everything was already done before us, and
this is what I managed to find. Not very detailed study of repositories on Github shows that only
active_record-acts_as lives and develops from them. I will not duplicate the Readme, it is quite clearly described how to use the heme. A quick glance at the
issues shows that the project is still in the initial phase, but IMO is quite applicable with adequate test coverage.
Have you encountered a similar problem? Are you aware of other solutions? I will be glad to hear your opinion in the comments.