I'm really struggling to understand how polymorphic relationships worm in Ember Data (Beta 11) and cannot find any update information on how to set them up and what is expected in the JSON payload. I'm trying to create a feed of items (think facebook feed) where you have different types of items in the feed. My modeling looks something like the following.
App.Feedable = DS.Model.extend({
activities: DS.hasMany('activity')
});
App.Activity = DS.Model.extend({
feedable: DS.belongsTo('feedable', { polymorphic: true, async: false })
});
App.MemberLikeShare = DS.Model.extend({
status: DS.attr('string')
});
App.PhotoShare = DS.Model.extend({
status: DS.attr('string'),
photo: DS.attr('string')
});
When I do a fetch at /activities I send back JSON that looks like the following:
{
activities: [
{
id: 1,
feedable: { id: 1, type: 'memberLikeShare' }
},
{
id: 4,
feedable: { id: 4, type: 'memberLikeShare' }
},
{
id: 5,
feedable: { id: 5, type: 'photoShare' }
}
],
member_like_shares: [
{
id: 1,
status: 'Foo'
},
{
id: 4,
status: 'Bar'
}
],
photo_shares: [
{id: 5, photo: 'example.jpg'}
]
}
When this runs I get an error like:
You can only add a 'feedable' record to this relationship Error: Assertion Failed: You can only add a 'feedable' record to this relationship
I'm assuming my relationships are wrong or I'm sending the wrong JSON?
polymorphic relationships should extend the base type.
App.Feedable = DS.Model.extend({
activities: DS.hasMany('activity')
});
App.MemberLikeShare = App.Feedable.extend({
status: DS.attr('string')
});
App.PhotoShare = App.Feedable.extend({
status: DS.attr('string'),
photo: DS.attr('string')
});
I'd also expect them to define the activities on them.
member_like_shares: [
{
id: 1,
status: 'Foo',
activites: [1,2,3,4]
},
{
id: 4,
status: 'Bar',
activites: [1,2,3,4]
}
],
photo_shares: [
{
id: 5,
photo: 'example.jpg',
activites: [1,2,3,4]
}
]
Related
I've got a very basic Price model that looks like this:
App.Price = DS.Model.extend({
value: DS.attr()
});
App.Price.reopenClass({
FIXTURES: [
{ id: 1, value: 29.99 },
{ id: 2, value: 39.99 },
{ id: 3, value: 49.99 },
{ id: 4, value: 55.99 }
]
});
Here's the route that's using this model:
App.PricingRoute = Ember.Route.extend({
model: function(){
return this.store.find('price');
}
});
In the controller, I set the sorting to be based on the value attribute:
App.PricingController = Ember.ArrayController.extend({
sortProperties: ['value'],
sortAscending: true
});
Then my template (in Jade) where I want them to be display in sorted order:
{{#each price in this}}
li.price-levels__value {{price.value}}
.price-levels__remove("{{action 'delete' price.id}}")
{{/each}}
Problem is they're not sorted. Interesting fact is that if I change the type of the value attribute to strings, the sorting DOES work.
eg.
{ id: 1, value: '29.99' }
{ id: 2, value: '39.99' }
etc.
So how do I get the sorting to work on a numerical model attribute?
here is a working jsbin: http://emberjs.jsbin.com/EnOqUxe/71/edit
What i´d like to have is there the company doesn´t need any reference to the person.
non working code
App.Company.FIXTURES = [
{ id: 1, name: 'Microsoft'},
{ id: 2, name: 'Apple'}
];
App.Person.FIXTURES = [
{ id: 1, name: 'Steve Jobs', company:2},
{ id: 2, name: 'Bill Gates', company:1},
{ id: 3, name: 'Steve Ballmer', company:1}
];
How can i achieve this?
thank you
You're practically there. You just need to fix up the models a bit:
App.Company = DS.Model.extend({
name: DS.attr('string')
});
App.Person = DS.Model.extend({
name: DS.attr('string'),
company: DS.belongsTo('company', {async:true})
});
And change your model hook, since now you link to companies through people, not people through companies.
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('person');
}
});
http://emberjs.jsbin.com/EnOqUxe/72/edit
I'm new to Ember and i have problem with display hasMany relation.
My Models:
App.Shop = DS.Model.extend({
name: DS.attr('string'),
openSettings: DS.hasMany('App.OpenSetting')
});
App.OpenSetting = DS.Model.extend({
title: DS.attr('string'),
data: DS.attr('string'),
shopId: DS.belongsTo('App.Shop')
});
I have mapping:
DS.RESTAdapter.map('App.Shop', {
openSettings: { key: 'openSettings' }
});
DS.RESTAdapter.map('App.OpenSetting', {
shopId: { key: 'shopId' }
});
In index.html in script i have:
{{#each model}}
{{id}} - {{name}} #
{{#each openSettings}}
{{title}}
{{/each}}
{{/each}}
But when object Shop has some relations in openSettings (openSettings:[1,2]) then i get error:
Uncaught RangeError: Maximum call stack size exceeded
What i'm doing wrong?
Fixtures:
App.Shop.FIXTURES = [
{
name: "Supermarket",
id: 2,
openSettings: [
2, 5
]
}
];
App.OpenSetting.FIXTURES = [
{
title: "monday - friday",
data: "8:00 - 24:00",
id: 2,
shopId: 2
},
{
title: "saturday",
data: "8:00 - 1:00",
id: 5,
shopId: 2
}
];
Thanks for help.
Ember throws that error when field is named "data". After change, all works fine.
I'm trying to figure out how to populate a table from a JSON object.
My JSON is a structurated object:
{
id: 0,
list: [{ username:'user_1',online:true, user:0 },
{ username:'user_2',online:true, user:0 }]
}
My Model is defined as follow:
MyTalk.WUser = DS.Model.extend({
list: DS.hasMany('MyTalk.User')
});
MyTalk.User = DS.Model.extend({
username: DS.attr('string'), // primary key
online: DS.attr('boolean'),
user: DS.belongsTo('MyTalk.WUser')
});
I am using a custom Adapter for ember-data:
DS.SocketAdapter = DS.RESTAdapter.extend(MyTalk.WebSocketConnection, {
// code not relevant
}
DS.SocketAdapter.map('MyTalk.WUser', {
list: {embedded: 'always'}
});
DS.SocketAdapter.map('MyTalk.User', {
primaryKey: 'username'
});
MyTalk.Store = DS.Store.extend({
revision: 12,
adapter: DS.SocketAdapter.create({})
});
Now I would load my data. I run in Chrome command line the following statements:
var store = DS.get('defaultStore');
var obj = {
id: 0,
list: [{ username:'user_1',online:true, user:0 },
{ username:'user_2',online:true, user:0 }]
};
var store.loadMany(MyTalk.WUser,obj);
var record = MyTalk.WUser.find(0);
record.serialize();
But it returns no record:
> Object {list: Array[0]}
thanks in advance!!
If you want to allow the adapter to deserialize embedded records (or perform any custom deserialization, for that matter), you'll need to load your data through the adapter rather than directly into the store.
var store = DS.get('defaultStore'),
obj = {
id: 0,
list: [{ username:'user_1', online:true, user:0 },
{ username:'user_2', online:true, user:0 }]
},
type = MyTalk.WUser,
adapter = store.adapterForType(type);
adapter.load(store, type, obj);
I get this assertion when run the code below:
Emptying a view in the inBuffer state is not allowed and should not
happen under normal circumstances. Most likely there is a bug in your
application. This may be due to excessive property change
notifications.
Link to demo:
http://plnkr.co/edit/s3bUw4JFrJvsL690QUMi
var App = Ember.Application.create({
Store: DS.Store.extend({
revision: 4,
adapter: DS.FixtureAdapter.create()
}),
Router: Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: "/",
connectOutlets: function(router){
var person;
person = App.Person.find(657);
person.addObserver("isLoaded", function() {
return router.get('router.applicationController').connectOutlet("things", person.get("things"));
});
}
})
})
}),
ApplicationController: Em.Controller.extend(),
ApplicationView: Em.View.extend({
template: Em.Handlebars.compile("{{outlet}}")
}),
ThingsController: Em.ArrayController.extend({
thingTypes: (function() {
return App.ThingType.find();
}).property()
}),
ThingsView: Em.View.extend({
template: Em.Handlebars.compile([
'{{#each controller.thingTypes}}',
'{{this.name}}',
'{{/each}}',
'{{#each controller.content}}',
'{{this.title}}',
'{{/each}}'].join(""))
}),
//MODELS
Person: DS.Model.extend({
things: DS.hasMany('App.Thing', {
embedded: true
})
}),
Thing: DS.Model.extend({
description: DS.attr('string'),
thingType: DS.belongsTo("App.ThingType", {
embedded: true
}),
title: (function() {
return this.get("thingType.name");
}).property("description")
}),
ThingType: DS.Model.extend({
name: DS.attr("string")
})
});
App.Person.FIXTURES = [
{
id: 657,
things: [
{
id: 1,
description: "Some text",
thing_type: {
id: 1,
name: "type 1"
}
}, {
id: 2,
description: "Some text",
thing_type: {
id: 2,
name: "type 2"
}
}
]
}
];
App.ThingType.FIXTURES = [
{
id: 1,
name: "type 1"
}, {
id: 2,
name: "type 2"
}, {
id: 3,
name: "type 3"
}
];
Why is this happening?
I was having the same error while trying to load a list of dropdown values from fixtures. What resolved it was overriding queryFixtures on the fixture adapter:
App.FixtureAdapter = DS.FixtureAdapter.extend
latency: 200
queryFixtures: (records, query, type) ->
records.filter (record) ->
for key of query
continue unless query.hasOwnProperty(key)
value = query[key]
return false if record[key] isnt value
true
I probably wouldn't have figured it out had I not set the latency first. Then the error was a bit more descriptive.
a bit late I guess... but I got it to work here:
http://plnkr.co/edit/hDCT4Qy1h5aE6GjM76qp
Didn't change the logic but where its called
I modified your router like this:
Router: Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: "/",
connectOutlets: function(router) {
var person;
router.set('router.applicationController.currentPerson', App.Person.find(657));
}
})
})
})
And created an ApplicationController:
ApplicationController: Em.Controller.extend({
currentPerson: null,
currentPersonLoaded: function() {
this.connectOutlet("things", this.get("currentPerson.things"));
}.observes("currentPerson.isLoaded"),
})
I dont know if this is the output you wished but the bug vanished!