Description
Let's add support for polymorphic model fields.
Rationale
Marten presently supports defining regular model relation fields such as many_to_one, one_to_one, and many_to_many. These fields allow targeting a single model class (target of the relation), but it is not possible to easily define a relation that can target various model classes.
To palliate this, let's introduce a new polymorphic model field that will work similarly to a many_to_one field while allowing targeting multiple model classes.
Usage
Basic definition
class Comment < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :content, :polymorphic, types: [Recipe, Article, Photo]
end
The polymorphic model field should require the use of a types option that should contain an array of model classes (the allowed model classes for the polymorphic relation). Internally, such fields should contribute two fields to the considered model: a <field_name>_id field containing the actual identifier of the targeted record and a <field_name>_type field containing the class name of the model of the targeted record.
Restrictions
A few restrictions should apply when defining polymorphic fields:
- They should not be defined as primary keys.
- All the model classes specified in the
types option should have primary keys of the same type.
Generated helpers
A few helper methods should be provided when dealing with model instances or model classes containing polymorphic fields:
comment = Comment.last!
# Regular field getters
comment.content # => Returns the targeted record
comment.content_id # => Returns the targeted record ID
comment.content_type # => Returns the targeted record class name
# Type class getter
comment.content_class # => Returns the model class of the targeted record
# Predicate helpers (generated based on the specified type classes)
comment.content_recipe? # => Returns true or false if the targeted record is a Recipe record
# Typed getters (generated based on the specified type classes)
comment.content_recipe # => Returns the associated Recipe record if the targeted record is indeed a Recipe record (or nil otherwise)
comment.content_recipe! # => Returns the associated Recipe record if the targeted record is indeed a Recipe record (or raise otherwise)
# Type-specific model scopes (generated based on the specified type classes)
Comment.with_recipe_content # => Returns all the comments associated with a Recipe record
To do
Description
Let's add support for
polymorphicmodel fields.Rationale
Marten presently supports defining regular model relation fields such as
many_to_one,one_to_one, andmany_to_many. These fields allow targeting a single model class (target of the relation), but it is not possible to easily define a relation that can target various model classes.To palliate this, let's introduce a new
polymorphicmodel field that will work similarly to amany_to_onefield while allowing targeting multiple model classes.Usage
Basic definition
The
polymorphicmodel field should require the use of atypesoption that should contain an array of model classes (the allowed model classes for the polymorphic relation). Internally, such fields should contribute two fields to the considered model: a<field_name>_idfield containing the actual identifier of the targeted record and a<field_name>_typefield containing the class name of the model of the targeted record.Restrictions
A few restrictions should apply when defining
polymorphicfields:typesoption should have primary keys of the same type.Generated helpers
A few helper methods should be provided when dealing with model instances or model classes containing polymorphic fields:
To do