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';
}));
});
Related
I am very new at Ember/ED/EmberFire so apologies if this is a trivial question. I am able to save records to Firebase but I am unable to specify relationships to those records in my controller. I am using
DEBUG: Ember : 1.10.0
DEBUG: Ember Data : 1.0.0-beta.12
DEBUG: Firebase : 2.2.3
DEBUG: EmberFire : 1.4.3
DEBUG: jQuery : 1.11.2
I have a model as such:
var Patient = DS.Model.extend({
lastName: DS.attr('string'),
firstName: DS.attr('string'),
encounters: DS.hasMany('encounter', {async: true})
});
var Encounter = DS.Model.extend({
dateOfEncounter: DS.attr('string'),
patient: DS.belongsTo('patient', {async: true})
});
I am simply trying to specify the patient that my newly created encounter object is associated with. This is my controller:
actions: {
registerEncounter: function() {
var newEncounter = this.store.createRecord('encounter', {
dateOfEncounter: this.get('dateOfEncounter'),
patient: this.store.find('patient', '-Jl8u8Tph_w4PMAXb9H_')
});
newEncounter.save();
this.setProperties({
dateOfEncounter: ''
});
}
}
I can successfully create the encounter record in Firebase, but there is no associated patient property. All I get is
https://github.com/firebase/emberfire/issues/232
this.store.find('patient', '-Jl8u8Tph_w4PMAXb9H_') returns a promise.
Try this:
this.store.find('patient', '-Jl8u8Tph_w4PMAXb9H_').then(function(pat) {
var newEncounter = this.store.createRecord('encounter', {
dateOfEncounter: this.get('dateOfEncounter'),
patient: pat
});
newEncounter.save();
});
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.
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.
I have a list of products that will be loaded under the /products route, from there you can navigate to a single product under the /products/:product_id. This is my models and the route:
var Product = DS.Model.extend({
page_title: DS.attr('string'),
image: DS.attr('string')
});
var ProductComment = DS.Model.extend({
contents: DS.attr('string')
});
var ProductRoute = Ember.Route.extend({
model: function(params) {
return App.Product.find(params.product_id)
},
setupController: function(controller, model) {
controller.set('content', model);
}
});
On the product page I want to load the products and additionally the comments for a product. As I use an external Api I cant load the id of the comments into the product model. So now I want to load the comments in to the ProductsController. I tried like described in this SO but it doesn't work. I'm using EmberDatas RESTAdapter.
I came up with solution. In the modelAfter hook of the products route, check if the comments are loaded into the model using this.get('product_comments').content.length. If not, load the data using App.ProductComment.find({product_id: this.id}) and store them into the model.
App.ProductRoute = Ember.Route.extend({
afterModel: function(model) {
model.ensureComments();
}
});
Product = DS.Model.extend({
page_title: DS.attr('string'),
image: DS.attr('string'),
product_comments: DS.hasMany('App.ProductComment'),
ensureComments: function() {
var productcomments = this.get('product_comments');
if (!productcomments.content.length) {
App.ProductComment.find({product_id: this.id}).then(function(result) {
productcomments.pushObjects(result)
});
}
}
});
Struggling with populating Ember with data.
I'm using Rails as the backend, and when I hit /contacts.json (ContactsRoute), it returns a list of id, first, last -- works as expected.
However, when visiting a detail view (ContactRoute), I would like to hit /contacts/1.json and fetch details like email address, anniversaries, etc. But since I have a dynamic segment the model hook is skipped and none of the associations are available.
Question: what is the best approach for fetching additional data in a list/detail scenario?
Models:
App.Contact = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
company: DS.attr('string'),
emails: DS.hasMany('App.Email'),
});
App.Email = DS.Model.extend({
contact: DS.belongsTo('App.Contact'),
emailAddress: DS.attr('string'),
});
Route:
App.Router.map(function() {
this.resource('contacts');
this.resource('contact', {path: 'contacts/:contact_id'});
});
App.ContactsRoute = Ember.Route.extend({
init: function() {},
model: function() {
return App.Contact.find();
}
});
App.ContactRoute = Ember.Route.extend({
model: function(params) {
return App.Contact.find(params.contact_id);
}
});
Thanks in advance.
I just posted an answer to a similar problem here: https://stackoverflow.com/a/18553153/1254484
Basically, in your App.ContactRoute, override the setupController method:
setupController: function(controller, model) {
controller.set("model", model);
model.reload();
return;
}
I'm using this with the latest ember-data (commit ef11bff from 2013-08-26).