Emberjs Fixture adapter queryFixture not working - ember.js

I have been having an issue implementing the queryFixtures function in Emberjs-Data. I have the following code to define the Store:
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.FixtureAdapter.extend({
queryFixtures: function(fixtures, query, type) {
console.log(query);
console.log(type);
return fixtures.filter(function(item) {
for(prop in query) {
if( item[prop] != query[prop]) {
return false;
}
}
return true;
});
}
})
});
My Model looks like:
FireSurveyApp.User = DS.Model.extend({
userId: DS.attr('number'),
username: DS.attr('string'),
password: DS.attr('string'),
FirstName: DS.attr('string'),
LastName: DS.attr('string')
});
When i try to get the fixture data out i am using the following code:
var returnUser = this.store.find("User",{ username : "Ted"});
The function will return undefined, Is there a different way that i should be calling the queryFixtures function?
Thanks in advance.

I was able to figure out a solution. Set the store adapter back to DS.FixtureAdapter.
adapter: 'DS.FixtureAdapter'
Implement the queryFixtures Function in the ember-data js file as shown:
queryFixtures: function(fixtures, query, type) {
var key = Ember.keys(query)[0];
return fixtures.filterBy(key, query[key]);
},
After both these steps have been done I was able to query the fixture as shown above with no problem. Hope this helps anyone experiencing the same issue.

Related

Ember model find records without server request

I have an ember model Category:
export default DS.Model.extend({
name: DS.attr('string'),
img: DS.attr('string'),
url: DS.attr('string'),
cnt: DS.attr('number'),
// parent_id: DS.belongsTo('category', {
// inverse: 'children',
// async: true
// }),
parent_id: DS.attr('string'),
// children: DS.hasMany('category', {
// inverse: 'parent_id',
// async: true
// }),
children: DS.attr(),
isSelected: false,
isExpanded: false,
hasChildren: function() {
return this.get('children').get('length') > 0;
}.property('children').cacheable(),
isLeaf: function() {
return this.get('children').get('length') == 0;
}.property('children').cacheable()
});
In my index route I have:
export default Ember.Route.extend({
model: function() {
var store = this.store;
return Ember.ArrayProxy.create({
categories: store.find('category'),
menuTopCategories: store.find('category', { parent_id: 1 })
});
}
});
I'm using a RESTAdapter so the store.find will send two requests to the server: categories and categories?parent_id=1.
I would like to have only the first request and then filter through the categories. I tried store.all - since I saw it reuses the already fetch data, but I can't manage to apply the filter.
I've rewritten the menuTopCategories and I don't see a new request:
menuTopCategories: store.filter('category', function(category) {
return category.get('parent_id') === "1";
})
My problem right now is to get the root category (first one) without hardcoding the parent_id.

Implementing model filter

I have set up the following scaffolding for my Ember application.
window.App = Ember.Application.create({});
App.Router.map(function () {
this.resource('coaches', function() {
this.resource('coach', {path: "/:person_id"});
});
});
App.ApplicationAdapter = DS.FixtureAdapter.extend({});
App.Person = DS.Model.extend({
fname: DS.attr('string')
,lname: DS.attr('string')
,sport: DS.attr('string')
,bio: DS.attr('string')
,coach: DS.attr('boolean')
,athlete: DS.attr('boolean')
});
App.Person.FIXTURES = [
{
id: 10
,fname: 'Jonny'
,lname: 'Batman'
,sport: 'Couch Luge'
,bio: 'Blah, blah, blah'
,coach: true
,athlete: true
}
,{
id: 11
,fname: 'Jimmy'
,lname: 'Falcon'
,sport: 'Cycling'
,bio: 'Yada, yada, yada'
,coach: false
,athlete: true
}
];
I am trying to set up a route to filter the person model and return only coaches. Just to make sure I can access the data, I have simply used a findAll on the person model.
App.CoachesRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('person');
}
});
Now though, I am trying to implement the filter method detailed on the bottom of the Ember.js Models - FAQ page.
App.CoachesRoute = Ember.Route.extend({
model: function() {
var store = this.store;
return store.filter('coaches', { coach: true }, function(coaches) {
return coaches.get('isCoach');
});
}
});
The coaches route is not working at all with the new route implemented and the old one commented out. I am using the Ember Chrome extension and when using the filter route the console responds with, Error while loading route: Error: No model was found for 'coaches'. Apparently the route is not working, specifically the model. No kidding, right? What am I missing in my filter model route?
Thank you in advance for your help.
The error message is spot on- there is no CoachModel. I think you need to do this:
App.CoachesRoute = Ember.Route.extend({
model: function() {
var store = this.store;
return store.filter('person', { coach: true }, function(coaches) {
return coaches.get('isCoach');
});
}
});

How to dynamically load fixtures in ember.js

Hey I'm having trouble dynamically loading fixture data into my emberjs models. How should I go about doing this? The addArtist function at the bottom will add one song correctly but I'm not sure how to adapt this to loading all of the songs into the data store correctly. Is there an easier way than adding each one individually?
App.Store = DS.Store.extend({
revision: 13,
adapter: 'DS.FixtureAdapter'
});
App.Artist = DS.Model.extend({
name: DS.attr('string'),
tracks: DS.hasMany('App.Tracks')
});
App.Tracks = DS.Model.extend({
videoid: DS.attr('string'),
title: DS.attr('string'),
duration: DS.attr('number')
});
App.Artist.FIXTURES = [];
App.Tracks.FIXTURES = [];
App.loadFixtures = function(){
$.getJSON('/artists', function(data){
$.each(data.artists, function(i,v){
App.Artist.createRecord(v);
});
});
$.getJSON('/tracks', function(data){
$.each(data.tracks, function(i,v){
App.Tracks.createRecord(v);
});
});
};
App.addArtist = function(){
var artist = App.Artist.createRecord({
id: 3,
name: 'Justin Martin'
});
var track = App.Tracks.createRecord({
id: 300,
title: 'Jungle Mix',
duration: 200
});
artist.get('tracks').pushObject(track);
};
Sample JSON Responses:
{"artists":[
{"id":1,"name":"The (International) Noise Conspiracy","track_ids":[1,2,3,4]},
{"id":2,"name":"0SM","track_ids":[5]},
{"id":3,"name":"2am","track_ids":[6,7,8]}
]}
{"tracks":[
{"id":1,"videoid":"FyjmCg_VMU0","title":"Smash It Up","duration":197},
{"id":2,"videoid":"jKXWm9yi4DY","title":"Only Lovers Left Alive","duration":162},
{"id":3,"videoid":"fwbleH55CCk","title":"Up For Sale","duration":211},
{"id":4,"videoid":"50JdKhIB1EQ","title":"A New Morning, Changing Weather","duration":270},
{"id":5,"videoid":"bd6ve0ydHVo","title":"The Landing feat. Alex G - Original Mix","duration":322},
{"id":6,"videoid":"RnwVtbMW4x4","title":"Anxious","duration":238},
{"id":7,"videoid":"Yo0zsqa06ZE","title":"I Did Wrong","duration":305},
{"id":8,"videoid":"_9ydBAgg130","title":"I Love You (feat. Baekchan & Joohee)","duration":219}
]}
Should I include the track_ids in the Artists response or do they get added when I call this method?
artist.get('tracks').pushObject(track);

Unable to query Emberjs Model when using DS.FixtureAdapter

I'm unable to query my models. I don't know what I'm doing wrong.
I have my store defined as
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.FixtureAdapter
});
And my model defined,
var Feature = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
parent: DS.belongsTo('SimpleTestManager.Feature'),
DS.belongsTo('SimpleTestManager.Project'),
children: DS.hasMany('SimpleTestManager.Feature'),
requirements: DS.attr('string')
});
App.Feature.adapter = DS.FixtureAdapter.create();
App.Feature.FIXTURES = [
{
id: 1,
name: "my first feature",
description: "some description",
parent: null,
project: 1,
children:[2],
requirements: "This is my first feature. It has many requirements."
},
{
id: 2,
name: "a sub feature",
description: "some sub feature.",
parent: 1,
project: 1,
children:[],
requirements: "This is a sub feature."
}
];
When I run the following in the command line
>>App.Features.find({id:'1'})
Error: assertion failed: Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.
I managed to solve the mentioned error by using David Lai's answer, but without extending from DS.Store (the new way after Ember Data 1.0.beta.1):
App.FixtureAdapter = DS.FixtureAdapter.extend({
queryFixtures: function(records, query, type) {
return records.filter(function(record) {
for(var key in query) {
if (!query.hasOwnProperty(key)) { continue; }
var value = query[key];
if (record[key] !== value) { return false; }
}
return true;
});
}
});
App.Store = DS.Store.extend({
adapter: 'Fixture'
});
Thanks for your help in trying to figure this out.
From what I've been able to gather, the find() method calls findQuery(), which calls queryFixtures() in the FixturesAdapter. The idea for this not being implemented is for developers to extend this to implement their own find() for stubbing out different search results. For a basic filter on parameter, I was able to just do this.
////// Stub data store fixture adapter ///////
App.Store = DS.Store.extend({
revision: 12,
//adapter: 'DS.RESTAdapter',
adapter: DS.FixtureAdapter.extend({
queryFixtures: function(fixtures, query, type) {
console.log(query);
console.log(type);
return fixtures.filter(function(item) {
for(prop in query) {
if( item[prop] != query[prop]) {
return false;
}
}
return true;
});
}
})
});
I guess your problem is that your are missing the App prefix you have already defined, and also the DS prefix for ember-data. You can also remove Feature.adapter = EmberData.FixtureAdapter.create();.
I've edited your code (not tested).
App.Store = DS.Store.extend({
revision: 12,
adapter: 'DS.FixtureAdapter'
});
App.Feature = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
parent: DS.belongsTo('SimpleTestManager.Feature'),
project:DS.belongsTo('SimpleTestManager.Project'),
children: DS.hasMany('SimpleTestManager.Feature'),
requirements: DS.attr('string')
});
App.Feature.FIXTURES = [
{
id: 1,
name: "my first feature",
description: "some description",
parent: null,
project: 1,
children:[2],
requirements: "This is my first feature. It has many requirements."
},
{
id: 2,
name: "a sub feature",
description: "some sub feature.",
parent: 1,
project: 1,
children:[],
requirements: "This is a sub feature."
}
];
Now to query a specific id you should use:
App.Feature.find(1);
To query by a property you can do:
App.Feature.findQuery({ name: "a sub feature" });
This should work.
Hope it helps
The issue here is that the fixture adapter doesn't actually implement any query methods. If you want to find a record by its ID you can simply call App.Feature.find(id) but anything more complicated than that isn't supported. Even with the DS.RESTAdapter you have to define your own query interface on the server to make queries work properly.

Embedded hasMany attribute access gives "TypeError: Cannot call method 'hasOwnProperty' of undefined"

Using:
Ember commit a5d45f66e1 from Jan 3, 2013)
Ember-Data commit 508479dee7 from Jan 4, 2013
Similar to this question ('Unable to get hasMany association'), I am unable to access embedded hasMany records directly but can see them through the model's content attribute.
For JSON:
{
"ref_book_search":{
"query":"har",
"results":[
{
"publisher":{
"name":"Pangolin",
"created":"2012-09-10T18:38:27.259515",
"id":"3d2028e4fb91181e1a6e012313914f821",
"is_active":true,
"main_url":null,
"resource_uri":"/api/v1/ref_publisher/3d2028e4fb91181e1a6e012313914f821"
},
"genre":"romcom",
"id":"cc671f00fc2711e1e41612313914f821",
"resource_uri":"/api/v1/ref_book/cc671f00fc2711e1e41612313914f821",
"title":"Harry Placeholder and the Goblet of PBR"
},
{
"publisher":{
"name":"Hoof & Mouth",
"created":"2012-10-10T14:31:27.259515",
"id":"3d200e9afb9811e1a27417383914f821",
"is_active":true,
"main_url":null,
"resource_uri":"/api/v1/ref_publisher/3d200e9afb9811e1a27417383914f821"
},
"genre":"horror",
"id":"cc621f08fc2711e1b81612313914e821",
"resource_uri":"/api/v1/ref_book/cc621f08fc2711e1b81612313914e821",
"title":"Harvey Weinstein Holiday Cookbook"
}
]
}
}
And app.js (note the map statements, which were the solution suggested in the prior question):
var App = Ember.Application.create();
DS.RESTAdapter.configure("plurals", {"ref_book_search" : "ref_book_search"});
App.store = DS.Store.create({
revision: 11,
adapter: DS.RESTAdapter.create({
bulkCommits: false,
namespace: "api/v1"
})
});
DS.RESTAdapter.map('App.RefBookSearch', {
primaryKey: 'query'
});
App.store.adapter.serializer.map('App.RefBookSearch', {
results: {embeddded: 'load'}
});
App.store.adapter.serializer.map('App.RefBook', {
publisher: {embeddded: 'load'}
});
App.RefPublisher = DS.Model.extend({
name : DS.attr('string'),
created : DS.attr('date'),
isActive : DS.attr('boolean'),
mainUrl : DS.attr('string')
});
App.RefBook = DS.Model.extend({
publisher: DS.belongsTo('App.RefPublisher'),
title : DS.attr('string'),
genre : DS.attr('string')
});
App.RefBookSearch = DS.Model.extend({
query: DS.attr('string'),
results: DS.hasMany('App.RefBook')
});
App.Router.map(function(match) {
match('/').to('query'),
match('/query/:ref_book_search_id').to('query')
});
App.QueryController = Ember.Controller.extend({
bookSearch: null,
results: []
});
App.QueryRoute = Ember.Route.extend({
setupControllers: function(controller, refBookSearch) {
controller.set('bookSearch', refBookSearch)
controller.set('results', refBookSearch.get('results').content)
}
})
App.initialize();
Everything looks fine at first, just like other poster:
search = App.RefBookSearch.find('ha')
search.get('query')
// => "ha"
results = search.get('results')
results.get('firstObject') instanceof App.RefBook
// => true
But then:
results.forEach(function(result) { console.log(result.get('title')) })
// => TypeError: Cannot call method 'hasOwnProperty' of undefined
Accessing via content shows the data is there:
results.content.forEach(function(result) { console.log(result.title) })
// => Harry Placeholder and the Goblet of PBR
// => Harvey Weinstein Holiday Cookbook
Now if I try accessing directly again, I get a slightly different error:
results.forEach(function(result) { console.log(result.get('title')) })
// => undefined x 2
This may or may not be related to this bug filed a few days ago.
I feel like I've tried everything here; I hope I'm just missing something simple. Any pointers very much appreciated. Thanks.
This is what ultimately worked for me. There seems to be some order-of-operations sensitivity i.e., doing the configure and map before creating the store. Also note that adapter.map is a convenience function that performs the mapping on the serializer.
App.Adapter = DS.RESTAdapter.extend()
App.Adapter.configure("plurals", {
"ref_book_search" : "ref_book_search",
"ref_book" : "ref_book",
"ref_publisher" : "ref_publisher"
});
App.Adapter.configure('App.RefBookSearch', {
primaryKey: 'query'
});
App.Adapter.map('App.RefBookSearch', {
results: {'embedded': 'load'}
});
App.Adapter.map('App.RefBook', {
publisher: {'embedded': 'load'}
});
App.store = DS.Store.create({
revision: 11,
adapter: App.Adapter.create({
bulkCommits: false,
namespace: "api/v1"
})
});