In most Rails guides that I came across, in the examples on polymorphic links there is an interesting feature of choosing the type for these links, which will be discussed in this post.
In Rails, connections made between objects of different types are considered polymorphic. It is assumed that all these objects share some common characteristics, but have different qualitative representations. Polymorphic relationships are one of the ways to implement a supertype-subtype relationship.
Consider three models:
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
class Post < ActiveRecord::Base has_many :comments , :as => :resource end class Image < ActiveRecord::Base has_many :comments , :as => :resource end class Comment < ActiveRecord::Base belongs_to :resource , :polymorphic => true end
Such a scheme requires the resource_type and resource_id fields for the Comment model, and in Rails guides, resource_type is defined as VARCHAR (255) as standard. For a long time I did not pay any attention to this, but the other day I thought, why not make this field the type
Enum ('Post', 'Image') NOT NULL , because with a certain number of models involved in the polymorphic connection this should not cause no problems and works faster.
')
To see the benefits of using ENUM, I had a little experience and made two Rails applications with the models listed above. For each application, a special script formed two identical data sets as follows: generated 1000 posts and pictures, then 1,000,000 comments randomly so that each created comment was randomly associated with a random post or picture. With this, I wanted to get the location of comments at odds, although a composite index (resource_type, resource_id) was introduced.
After generating the data, I carried out control samples for posts with id 100,200, ..., 1000, and I give the results of the experiment in the table. Tests were conducted on MySQL version 5.1.37–1ubuntu5

A small explanation of the table:
T1 - table with resource_type VARCHAR (10) NOT NULL.
T2 - table with resource_type ENUM ('Post', 'Image') NOT NULL.
Columns 3 and 5 contain the execution time of the request
SELECT * FROM `comments` WHERE resource_type = 'Post' AND resource_id = N1 ;.
Columns 4 and 6 contain the execution time of the request
SELECT * FROM `posts` INNER JOIN comments ON` comments`.resource_type = 'Post' AND `comments`.resource_id =` posts`.id WHERE `posts`.id = N1.
N - number of experience, N1 = N * 100.
After that, I think it makes sense to use ENUM fields for polymorphic links. But for the time being it is not clear to me what are the pitfalls? What are your thoughts on polymorphic connections and their use in the national economy :)?