How do I set up polymorphic relationships using ember-data - ember.js

So lets say a recipe has several ingredients of differing amounts.
Recipe Model
var Recipe = DS.Model.extend({
name: DS.attr('string'),
ingredients: DS.hasMany('ingredient')
});
Ingredient Model
var Ingredient = DS.Model.extend({
name: DS.attr('string'),
recipes: DS.hasMany('recipe'),
// amount?
});
So the amount of each ingredient would depend on the recipe. However on its own the ingredient will not have an amount.
How would you go about modeling that data? Right now I am using the FixtureAdapter until I finish building the interface.
Using Ember 1.5.1 and Ember-Data 1.0.0-beta.7+canary.b45e23ba.

To answer your first question:
Define the model like so
App.Comment = DS.Model.extend({
message: DS.belongsTo('message', {
polymorphic: true
})
});
And the property needs an additional property propertyType, defining the relationship type
{
"message": 12,
"messageType": "post"
}
https://github.com/emberjs/data/blob/master/TRANSITION.md#polymorphic-relationships
Now to your second question, not sure if polymorphism would be necessary. I might just include a joining record
var RecipeIngredient = DS.Model.extend({
amount: DS.attr(),
ingredient: DS.belongsTo('ingredient')
});
var Recipe = DS.Model.extend({
name: DS.attr('string'),
ingredients: DS.hasMany('recipeIngredient')
});

Related

EmberJS simple ID from related object

is there any way to do some filtering based on the related ID? imagine I have 2 models one is a song model and the other is an album model so obviously the song has album with an id, the json will return the model with
{album: 1}
so if I wanna filter it seems that I can't compare the album id with something like
song.get('album.id') === 1
is there any way to do it so simply?
Thanks
Edit: models
App.Album = DS.Model.extend({
irrelevantstuff: DS.attr(),
songs: DS.hasMany('Song')
})
App.Song = DS.Model.extend({
irrelevantstuff: DS.attr(),
album: DS.belongsTo('Album')
})
I tried both with {async:true} and without, still same problem.
however I noticed that if I run it the first time it gives me undefined to all of the album.id but if I run it the second time I get the ids, now I have everything on the store, so it's not doing an AJAX request either the first or second time.
{"songs": [{"irrelevantstuff":"foo", "album": 1}, {"irrelevantstuff":"bar", "album": 1}]}
{"albums": [{"irrelevantstuff":"album", "songs": [1,2]}]
Relationships should be camelCase
App.Album = DS.Model.extend({
irrelevantstuff: DS.attr(),
songs: DS.hasMany('song', {async: true})
})
App.Song = DS.Model.extend({
irrelevantstuff: DS.attr(),
album: DS.belongsTo('album', {async: true})
})
Since your data for the relationship isn't coming down in the request for the song/album it would be considered async. As such if you want to access it you'll need to use it asynchronous methods, promises.
var songPromise = this.store.find('song', 1);
songPromise.then(function(song){
var albumPromise = song.get('album');
albumPromise.then(function(album){
// the album is available for usage....
if(album.get('id') == 1){
alert('woo hoo');
}
});
});

Emberjs (link-to HasMany) Error while loading route: TypeError: Cannot call method 'resolve' of undefined

I am trying to set model of a route(not nested) but with relationship belong to with setupController
Here is my JSBIN
i.e company hasMany Contacts
from companies list page I have directly linked to contacts page (want flow that ways)
I want to use the company model to get its contacts list but I am getting error
Error while loading route: TypeError: Cannot call method 'resolve' of undefined
Heres my Router
App.Router.map(function() {
this.resource('companies',{path:'/'});
this.resource('company',{path:'/company/:company_id'});
this.resource('contacts',{path:'/company/:id/contacts'});
});
This is what I am doing
App.ContactsRoute = Em.Route.extend({
setupController: function(controller, model) {
console.log(model.get('contacts')); //This line gives error
//controller.set('model',model.get('contacts'));
}
});
The MODEL
App.Company = DS.Model.extend({
name: DS.attr('string'),
contacts: DS.hasMany('Contact')
});
App.Company.FIXTURES = [{
id: 1,
name: 'company 1',
contacts: ['1']
}, {
id: 2,
name: 'company 2',
contacts: ['1', '2']
}];
App.Contact = DS.Model.extend({
name: DS.attr('string'),
company: DS.belongsTo('Company')
});
App.Contact.FIXTURES = [{
id: 1,
name: 'employee 1',
company: 1
}, {
id: 2,
name: 'employee 2',
company: 2
}];
Updated Fiddle
I updated the fiddle for you and changed a few things. To me, it seemed more logical to add contacts as a route of the resource company instead of a separate resource.
I also made the company model async, so it waits for all models to be loaded before actually rendering everything
Take a look and feel free to ask questions if you don't fully understand the solution.

Ember.js belongsTo is not displayed in view

I'm trying to display a model, with a hasMany relation and each of those relations has a belongsTo relation.
For some reason, Ember doesnt want to display the belongsTo.
Here are my models:
App.City = DS.Model.extend({
city: DS.attr('string')
});
App.Child = DS.Model.extend({
name: DS.attr('string'),
city: DS.belongsTo('city', {async: true})
});
App.Activity = DS.Model.extend({
children: DS.hasMany('child',{async:true}),
name: DS.attr('string')
});
My template looks like this:
Activity name: {{name}}<br />
{{#each child in children}}
Child name: {{child.name}}<br />
Child city name: {{child.city.name}}
{{/each}}
{{child.city.name}} is empty.
I've created a JSFiddle to illustrate the problem here: http://jsfiddle.net/N2xdx/
In your City fixtures you have:
App.City.FIXTURES = [
{
id: 1,
name: 'Aarhus'
}
];
But your App.City doesn't have a name: DS.attr('string') mapping. Update your model to the following, and all will work:
App.City = DS.Model.extend({
name: DS.attr('string'),
city: DS.attr('string')
});
This is a fiddle with this working http://jsfiddle.net/marciojunior/vDaxt/

Same Model for different relation

I want to use my File Model with two other models.
App.File = DS.Model.extend({
filename: DS.attr('string'),
//related:DS.belongsTo('App.Task' and 'App.Comment'),
});
App.Task = DS.Model.extend({
title: DS.attr('string'),
files:DS.hasMany('App.Files'),
});
App.Comment = DS.Model.extend({
comment:DS.attr('string'),
files:DS.hasMany('App.Files'),
});
The database structure has a related_id and related_type column. How can I set this up to work with ember?

How to subclass or inherit a model from another model using ember-data

Let's say my rails models look like this:
class SalesRelationship < ActiveRecord
end
Which is inherited by crossSell like this:
class crossSell < SalesRelationship
end
How do I show this inheritance relationship in ember-data. What is the best practise for this:
App.salesRelationship = DS.Model.extend({
name: DS.attr('string')
});
Can I create a subclass called 'crossSell', like this
crossSell = App.salesRelationship({
productName: DS.attr('string')
});
or like this
App.salesRelationship.crossSell = DS.Model.extend({
productName: DS.attr('string')
});
Pretty close, you can just extend SalesRelationship.
App.CrossSell = App.SalesRelationship.extend({
productName: DS.attr('string')
})
In Ember 2.7 it can be done like this. Assume you have a Person class and wish to inherit from it to make an Employee for a status field (like hired, retired, fired on-leave etc)
app/models/person.js
import DS from 'ember-data';
export default DS.Model.extend({
firstName: DS.attr(),
lastName: DS.attr(),
fullName: Ember.computed('firstName', 'lastName', function() {
return `${this.get('lastName')}, ${this.get('firstName')}`;
});
app/models/employee.js
import DS from 'ember-data';
import Person from './person';
export default Person.extend({
status: DS.attr(),
statusCode: DS.attr(),
});