-
Notifications
You must be signed in to change notification settings - Fork 30
Description
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]
endThe 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
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:
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 recordTo do
- Add basic support for polymorphic model field definitions.
- Make it possible to support reverse relations for polymorphic fields.
- Make it possible to filter query sets through reverse polymorphic relations.
- Make it possible to prefetch polymorphic relations.
- Make it possible to prefetch reverse polymorphic relations.
- Ensure that trying to "join" polymorphic relations results in an explicit error.
- Add documentation.