Ember data alias model / Map JSON response - ember.js

My server returns a JSON response like this:
{
artists: [{
id: "1",
first_name: "Foo",
last_name: "Bar"
}],
studios: [{
id: 1,
name: "Test",
// ...
artist_ids: ["1"]
}]
}
'artist' is in fact a User model but with a different name. How can I map artist to the User model? Maybe a bad explanation but if I rename the JSON response serverside to 'users' instead of 'artist' and use the models below everything works like I want. I simply want to use the name 'artist' instead of 'user', both server side and client side. Hope you guys understand what i mean.
App.Studio = DS.Model.extend
name: DS.attr 'string'
// ..
users: DS.hasMany 'App.User'
App.User = DS.Model.extend
firstName: DS.attr 'string'
lastName: DS.attr 'string'
studio: DS.belongsTo 'App.Studio'
I guess that the simplest thing to do would be something like artists: DS.hasMany 'App.User' but obviously this does not work.

First, I recommend using the latest Ember / EmberData, so relationships are defined like this:
App.Studio = DS.Model.extend({
name: DS.attr('string'),
// ..
users: DS.hasMany('user')
});
App.User = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
studio: DS.belongsTo('studio')
});
Next, I recommend using the ActiveModelAdapter if you are getting underscores in your response JSON:
App.ApplicationAdapter = DS.ActiveModelAdapter;
Finally, overriding typeForRoot and keyForRelationship in a custom serializer should fix your issue:
App.ApplicationSerializer = DS.ActiveModelSerializer.extend({
typeForRoot: function(root) {
if (root == 'artist' || root == 'artists') { root = 'user'; }
return this._super(root);
},
keyForRelationship: function(key, kind) {
if (key == 'users') { key = 'artists'; }
return this._super(key, kind);
}
});
Example JSBin
One last thing: you can even get rid of the custom keyForRelationship if you name the relationship artists in Studio:
App.Studio = DS.Model.extend({
name: DS.attr('string'),
// ..
artists: DS.hasMany('user')
});

Have you tried just creating an Artist model extended from User?
App.Artist = App.User.extend({})
I haven't tried it, but I suspect that might work.

Related

How can I create a record with a nested/embedded record in Ember Data?

How can I create a nested/embedded model when creating a record with Ember Data? Specifically, I want to create a post model with a nested/embedded model author. The following code gives me the error:
Error while processing route: index Assertion Failed: You cannot add a 'undefined' record to the 'post.author'. You can only add a 'author' record to this relationship. Error: Assertion Failed: You cannot add a 'undefined' record to the 'post.author'. You can only add a 'author' record to this relationship.
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('post', {
title: 'My first post',
body: 'lorem ipsum ...',
author: {
fullname: 'John Doe',
dob: '12/25/1999'
}
});
}
});
App.Post = DS.Model.extend({
title: DS.attr('string'),
body: DS.attr('string'),
author: DS.belongsTo('author')
});
App.Author = DS.Model.extend({
fullname: DS.attr('string'),
dob: DS.attr('string')
});
Any ideas on how to do this? I also created a demo on JSBin: http://emberjs.jsbin.com/depiyugixo/edit?html,js,console,output
Thanks!
Relationships need to be assigned to instantiated models, plain objects won't work.
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('post', {
title: 'My first post',
body: 'lorem ipsum ...',
author: this.store.createRecord('author', {
fullname: 'John Doe',
dob: '12/25/1999'
})
});
}

Ember - Querying model by properties in a related model

I'm trying query my post model for published posts that have a specific tag. My models look like this:
var Post = DS.Model.extend({
tags: DS.hasMany('tag', { async: true }),
title: DS.attr('string'),
published: DS.attr('boolean'),
});
var Tag = DS.Model.extend({
posts: DS.hasMany('post', { async: true }),
name: DS.attr('string')
});
I've been able to get published posts in my query using the find() method:
this.get('store').find('post', {published: true});
But I don't understand how to query for properties that are part of a related model. I'd appreciate any guidance, thanks!
Edit
I came up with this solution using filter() which seems to work well.
var self = this;
var store = this.get('store');
store.find('post', {published: true}).then(function() {
self.set('content', store.filter('post', function(post) {
return post.get('tag.name') === 'Photography';
}));
});

Ember Data - how to findBy with an associated hasMany

I have two objects User and Post. A user has many posts and a post belongs to a user.
How do I, within the user controller, use findBy or another method to get to a featured post with the posts array??
Here is how I implemented the UserController; however, the featuredPost computed property is coming back as undefined. Is this best approach? If so, what am I missing?
App.User = DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
client: DS.belongsTo('App.Client', { async: true }),
posts: DS.hasMany('App.Post', { async: true })
});
App.Post = DS.Model.extend({
client: DS.belongsTo('App.Client', { async: true }),
user: DS.belongsTo('App.User', { async: true }),
title: DS.attr('string'),
body: DS.attr('string'),
isFeatured: DS.attr('boolean')
});
App.UserController = Ember.ObjectController.extend({
needs: ['post'],
posts: (function() {
return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
content: this.get('content.posts')
});
}).property('content.posts'),
featuredPost: (function() {
return this.get('content.posts').findBy('isFeatured', true)
}).property('content.featuredPost'),
});
Take a look at this: http://emberjs.com/api/#method_computed_filterBy
App.UserController = Ember.ObjectController.extend({
featuredPost: Ember.computed.filterBy('posts', 'isFeatured', true)
});
Also, in
featuredPost: (function() {
return this.get('content.posts').findBy('isFeatured', true);
}).property('content.featuredPost')//should be observing 'posts'
You are basically observing content.featuredPost but from what youve mentioned that property doesnt exist, the property you should be observing is 'posts'. This is a mistake that i made when i was learning ember too, so felt like pointing out. Also using content is optional, you can directly observe the model associated with controller.
Also From doc, findBy seems to return just first item that matches the passed value, not all of them. So to get first match it should be
App.UserController = Ember.ObjectController.extend({
featuredPost: function() {
return this.get('posts').findBy('isFeatured', true);
}.property('posts')//assuming user model hasMany relation to posts
});
Also I would go with the latest version of ember data and make following changes:
App.User = DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
client: DS.belongsTo('client', { async: true }),
posts: DS.hasMany('post', { async: true })
});
App.Post = DS.Model.extend({
client: DS.belongsTo('client', { async: true }),
user: DS.belongsTo('user', { async: true }),
title: DS.attr('string'),
body: DS.attr('string'),
isFeatured: DS.attr('boolean')
});
This would be good read : https://github.com/emberjs/data/blob/master/TRANSITION.md
And here is a bare minimum working example : http://jsbin.com/disimilu/5/edit
Hope this helps.

Ember DS.Store error while submitting form

I'm a newbie to ember and I'm trying to create a basic sign-up form.
Relevant model:
App.NewUser = DS.Model.extend({
user_name: DS.attr('string'),
password: DS.attr('string'),
confirm_password: DS.attr('string'),
email: DS.attr('string'),
first_name: DS.attr('string'),
last_name: DS.attr('string'),
});
Relevant controller:
App.SignupController = Ember.ArrayController.extend({
actions: {
signup: function() {
var data = this.getProperties('first_name', 'last_name', 'email', 'user_name', 'password', 'confirm_password');
var newUser = this.store.createRecord('newUser', data);
newUser.save();
},
},
});
When the "signup" action executes, I get the following error:
Error: Attempted to handle event `didSetProperty` on <App.NewUser:ember332:null> while in state root.deleted.saved. Called with {name: last_name, oldValue: undefined, originalValue: undefined, value: undefined}.
What am I doing wrong?
This is a bug, Ember Data is setting the record state incorrectly if you're setting a value to what it's currently set to (undefined on createRecord)
You'll want to either coerce your values into empty strings or not set undefined values while creating the record.
for(var key in data){
if(!data[key]) delete data[key];
}
http://emberjs.jsbin.com/OxIDiVU/124/edit
https://github.com/emberjs/data/issues/1648

Create an associated model from JSON

I have a server response that looks like:
comments: [
0: {
body: "test3",
created_at: "2013-06-27T22:27:47Z",
user: {
email: "test#test.com",
id: 1,
name: "Tester"
}
}
]
And ember models:
App.Comment = DS.Model.extend({
user: DS.belongsTo('App.User'),
body: DS.attr('string')
});
App.User = DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
});
How do I create an ember user model from the server's response?
The solution if you're using rails active model serializers is to embed :ids, include: true:
app/serializers/comment_serializer.rb
class CommentSerializer < ActiveModel::Serializer
embed :ids, include: true
attributes :created_at, :body
has_one :user
end
Just like the readme for active_model_serializers says, this will produce:
{
"users":[
{
"id":1,
"name":"Tester",
"email":"test#test.com",
}
],
"comments":[
{
"event":"commented",
"created_at":"2013-06-27T22:27:47Z",
"body":"test3",
"user_id":1
}
]
}