I have 3 models: type
, restriction
and item
.
A type
is simple and just has an id
:
app/models/type.js
:
import Model from 'ember-data/model';
export default Model.extend({});
A restriction
can have many type
describing the allowable types for an item with this restriction:
app/models/restriction.js
:
import Model from 'ember-data/model';
import { hasMany } from 'ember-data/relationships';
export default Model.extend({
allowedTypes: hasMany( "type" )
});
An item
can have many type
but also can have many restriction
and the type
must only be a subset of the intersection of the allowed types for all the restrictions (and if there is at least one restriction then it must have at least one type).
I've implemented a validation for this using a computed property:
app/models/item.js
:
import Model from 'ember-data/model';
import { computed } from '@ember/object';
import { hasMany } from 'ember-data/relationships';
import { isEmpty } from '@ember/utils';
const peekHasMany = attr => ( item => item.hasMany( attr ).ids() );
const hasItems = array => !isEmpty( array );
const includedIn = array => ( item => array.indexOf( item ) >= 0 );
const intersectionOf = ( array1, array2, index ) => index >= 0 ? array1.filter( includedIn( array2 ) ) : array2;
export default Model.extend({
types: hasMany( "type" ),
restrictions: hasMany( "restriction" ),
isValidTypes: computed(
"types.[]",
"restrictions.@each.allowedTypes",
function(){
let restrictions = this.hasMany( "restrictions" ).value();
if ( isEmpty( restrictions ) )
{
return true;
}
let allowed = restrictions
.map( peekHasMany( "allowedTypes" ) )
.filter( hasItems );
if ( isEmpty( allowed ) )
{
return true;
}
let types = this.hasMany( "types" ).ids();
if ( isEmpty( types ) )
{
return false;
}
let allowedTypes = allowed.reduce( intersectionOf );
return types.every( includedIn( allowedTypes ) );
}
)
});
This uses the DS.Model.hasMany( attributeName )
to synchronously get the HasManyReference
for the relationships which relies on the referenced models being loaded.
How can I change the computed property to use this.get()
to asynchronously get both attributes (and the child attributes) rather than using this.hasMany()
synchronously?
Aucun commentaire:
Enregistrer un commentaire