Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relationships with Ember CLI Mirage

I'm new to Ember and I'm trying to create an easy app where I have 2 models, Mountains and Ranges. A range has many mountains while a mountain belongs to a range. I want to create a relationship between them. I've searched through the web but I've found different explanations and I'm still struggling with this problem.

My models are:

mountain.js

import DS from 'ember-data';
export default DS.Model.extend({
    name: DS.attr('string'),
    altitude: DS.attr('number'),
    range: DS.belongsTo('range', {async: true})
});

range.js

import DS from 'ember-data';
export default DS.Model.extend({
    name: DS.attr('string'),
    length: DS.attr('number'),
    mountains: DS.hasMany('mountain', {async: true})
});

My mirage/scenario/default.js file looks like this:

export default function(server) 
{
    var himalaya = server.create('range', {id: 1, name:'Himalaya', length:'16598' });
    var karakorum = server.create('range', {id: 2, name:'Karakorum', length:'34801' });

    var everest = server.create('mountain', {id:1, name: 'Everest', altitude: '8871', range_id:1 });
    var K2 = server.create('mountain', {id:2, name: 'K2', altitude: '8657', range_id:2 });
}

and these are mirage/factories/range.js and mirage/factories/mountain.js files:

import Mirage, {faker} from 'ember-cli-mirage';

export default Mirage.Factory.extend({

});

Is this the right way to set up a relationship with mirage in Ember-CLI ? I'd also like to show in the himalaya page (I've already created a route and a template) all the mountains that belong to the range himalaya. How can I achieve this?

Thanks in advance.

like image 202
splunk Avatar asked Sep 14 '15 10:09

splunk


2 Answers

Currently, you have to do relationship bookkeeping manually, so yes, you're going the right way. Note that you might want to update ranges with mountain ids:

var himalaya = server.create('range', {id: 1, name:'Himalaya', length:'16598' });
var karakorum = server.create('range', {id: 2, name:'Karakorum', length:'34801' });

var everest = server.create('mountain', {id:1, name: 'Everest', altitude: '8871', range_id:1 });
var k2 = server.create('mountain', {id:2, name: 'K2', altitude: '8657', range_id:2 });

server.db.ranges.update(himalaya.id,  {mountain_ids: [everest.id]});
server.db.ranges.update(karakorum.id, {mountain_ids: [k2.id]});

But Sam Selikoff is working hard on Mirage and soon it will be possible to do something like this:

var everest = server.create('mountain', {id:1, name: 'Everest', altitude: '8871' });
var k2 = server.create('mountain', {id:2, name: 'K2', altitude: '8657' });

var himalaya = everest.create('range', {id: 1, name:'Himalaya', length:'16598' });
var karakorum = k2.create('range', {id: 2, name:'Karakorum', length:'34801' });

I'd also like to show in the himalaya page (I've already created a route and a template) all the mountains that belong to the range himalaya. How can I achieve this?

The straightforward solution is to create the following Mirage routes:

  • mountains/:id
  • ranges/:id

If your relationships are synchronous, in your Ember range route you'll have to request a range, get its related mountain ids and request them too.

If your relationships are async, then you just have to request the range. Ember/ED will automatically request missing related records when they are accessed from the template. But this will cause a flash of missing data on the page.

A more elegant solution is sideloading. You only need a ranges/:id Mirage route. When a range is requested via that route, you have Mirage serve (sideload) related mountains in addition to the requested range.

Also take into consideration the JSON structure you're using. If you're using the oldschool adapter/serializer, the API is kinda arbitrary and you're fine. If you're using the new JSONAPI adapter, then you need to comply with the JSONAPI spec. In order to have certain data sideloaded, you need to explicitly ask for it.

JSONAPI serialization is not yet available in Mirage out of the box. Eventually you'll be able to use shorthands, but currently you'll have to manually format the data to the JSONAPI format.

like image 182
Andrey Mikhaylov - lolmaus Avatar answered Oct 23 '22 12:10

Andrey Mikhaylov - lolmaus


For those still coming across this answer, Mirage now has full association support.

http://www.ember-cli-mirage.com/docs/v0.3.x/models/

like image 28
Sam Selikoff Avatar answered Oct 23 '22 12:10

Sam Selikoff