- Previous ← One To Many Relationships
- Next → Many To One Relationships
- ⮐ Relationships Guide
Imagine our social network for trail runners 🏃🏃🏾♀️ allows runners to tag their activities. #runday #justdoit
In this model, the ActivityData might have multiple tags, but given that millions if not billions if not trillions of activities might use a tag like #neverstopexploring, it turns out we definitely don't want the tag to keep track of every activity that ever referenced it.
graph LR;
A(ActivityData) == tags ==> B(Hashtag)
Note In our charts we use dotted lines for singular relationships and thick solid lines for collection relationships.
Often ManyToNone
is used for exactly this sort of case, where conceptually the relationship is many-to-many in nature, but one side would be so large that modeling it as such is prohibitive.
Here's how we can define such a relationship via various mechanisms.
Note Models are currently the primary way that users of EmberData define "schema".
Models are not the only way to define schema today, but they are the most immediately available ergonomic way to do so.
When using Models, EmberData parses schema from them at runtime, converting static information defined on the class into the json schema format needed by the rest of the system.
This is handled by the implementation of the schema service provided
by the @ember-data/model
package. The service converts the class
definitions into the json definitions described in the next section.
🏷️ Hashtag
import Model, { attr } from '@ember-data/model';
export default class Hashtag extends Model {
@attr name;
}
🏃🏾♀️ ActivityData
import Model, { hasMany } from '@ember-data/model';
export default class ActivityData extends Model {
@hasMany('hashtag', { async: false, inverse: null })
tags;
}
EmberData doesn't care where your schemas come from, how they are authored, or how you load them into the system so long as when it asks the schema service for information it gets back field definitions in the right json shape.
Here, we show how the above trail runner relationship is described by a field definition.
Current
🏃🏾♀️ ActivityData
{
"kind": "hasMany",
"name": "tags",
"options": { "async": false, "inverse": null },
"type": "hashtag",
}
🚧 Coming Soon
Because we deprecated implicit option values in 4.x, we are now able to change defaults.
This means that the next iteration of Schema will be able to reliably use the The lack of an option like "async" or "inverse" as a false-y value.
We also are shifting the value for "kind" from "belongsTo" to "resource" to make it more readil clear that relationships do not (by default) have directionality or ownership over their inverse.
🏃🏾♀️ ActivityData
{
"kind": "collection",
"name": "tags",
"type": "hashtag",
}
Working with schemas in a raw json format is far more flexible, lightweight and performant than working with bulky classes that need to be shipped across the wire,parsed, and instantiated. Even relatively small apps can quickly find themselves shipping large quantities of JS just to describe their data.
No one wants to author schemas in raw JSON though (we hope 😬), and the ergonomics of typed data and editor autocomplete based on your schemas are vital to productivity and code quality. For this, we offer a way to express schemas as typescript using types, classes and decorators which are then compiled into json schemas and typescript interfaces for use by your project.
🏷️ Hashtag
import { field } from '@warp-drive/schema';
export class Hashtag extends Model {
@field name: string;
}
🏃🏾♀️ ActivityData
import { collection } from '@warp-drive/schema';
import { Hashtag } from './hashtag';
export class ActivityData extends Model {
@collection(Hashtag) tags;
}
Support for migrating from @ember-data/model
on a more granular basis is provided by decorators that preserve the semantics of the quirks of that class. This allows you to begin eliminating models
and adopting other features of schemas sooner.
🏷️ Hashtag
import { attr } from '@warp-drive/schema/legacy';
export class Hashtag extends Model {
@attr name: string;
}
🏃🏾♀️ ActivityData
import { hasMany } from '@warp-drive/schema/legacy';
import { Hashtag } from './hashtag';
export class ActivityData extends Model {
@hasMany(Hashtag) tags;
}
---
- Previous ← [One To Many Relationships](./2-one-to-many.md)
- Next → [Many To One Relationships](./4-many-to-one.md)
- ⮐ [Relationships Guide](../index.md)