The Problem
At the time of writing Ember Data only handles polymorphic associations. This doesn’t cover many common use cases because it enforces the polymorphism to only be used in associations.
Example
Imagine I have a model called Work
which has many tasks. There are many kinds of tasks, so naturally in OOP I would define Task
as a super class with all the common properties and then extend it with specific properties with subclasses.
App.Work = DS.Model.extend({
name: DS.attr('string'),
tasks: DS.hasMany('task')
});
App.Task = DS.Model.extend({
description: DS.attr('string')
date: DS.attr('date')
});
App.RepairTask = App.Task.extend({
timeRequired: DS.attr('number'),
operator: DS.attr('string')
});
App.CleaningTask = App.Task.extend({
usedWater: DS.attr('number')
});
When I request /task/1
, for example, the server returns the JSON (I’m using ActiveModelSerializer for ED, but that’s irrelevant here):
{
"task": {
"id":1,
"type":"repairTask",
"description": "I'm repairing this right away!",
"timeRequired":5.4,
"operator":"Tom"
}
}
The code this.store.find('task')
returns a Task
object and not a RepairTask
with the additional properties (imagine, relationships) like desired.
Proposal
Querying
Whenever a query is made, if the type is a subclass of DS.Model and it has been subclassed, Ember Data should look for type information to determine the correct concrete bottommost class to instantiate.
The string in a type
property is a common way to go and should be the default, but ideally we should abstract the concrete type determination logic to the user.
Saving
Likewise, when we save a concrete subclassed model (RepairTask
, for example), a POST request should be sent to /tasks
along with its type information (in this case a type
property with repairTask
value).
Bottomline and other toughts
This approach would make polymorphic:true
useless, since associations would be naturally covered as well. Accessing the tasks
property would trigger all this behaviour since Task
isn’t a concrete subclass of DS.Model
.
This approach is common in JSON processors like [Jackson][1], and with [JPA][2] ORM’s like [Hibernate][3]. The typical way to deal with inheritance in JSON is to include the type information in a reserved field.
Before version 1 of Ember Data we were dealing with this problem like this: https://coderwall.com/p/hi6hya
Basically we were overriding the materialize
hook and then we changed the record.constructor
and applied an existing mixin based on the type
property.
With Ember Data 1 the nearest solution I found was this one (question has before v1, answer has v1). However, with that solution relationships don’t work, and logic related to the specific properties in the mixin are not applied (like converting to camel case, for example).
Am I missing something here? Thank you for your time.