Uncaught #<error> on loading fixtures - ember.js

I'm doing something wrong with fixtures.
I have to models where a Contract has many Contractitems and try to load fixtures for them
App.Contract = DS.Model.extend({
contractItems: DS.hasMany('contractItem'),
//
});
App.ContractItem = DS.Model.extend({
contract: DS.belongsTo('contract'),
//
});
App.Contract.FIXTURES = [{
id: 1,
runtime: 12,
//
contractItems: [1, 2]
},{
id: 2,
//
}];
App.ContractItem.FIXTURES = [{
id: 1,
//
},{
id: 2,
//
}];
I commented out some dull attrubutes, but the full file is up here.
When I load the page, i get an Error
Uncaught #<error> VM1615:956
ProfileManager.ended VM1615:956
Ember.subscribe.after VM1615:2007
finalizer ember-1.5.1.js:1802
Ember.tryCatchFinally ember-1.5.1.js:1554
Ember.Instrumentation.instrument ember-1.5.1.js:1810
Ember.CoreView.Ember.Object.extend.renderToBuffer ember-1.5.1.js:22472
Ember.View.Ember.CoreView.extend.createElement ember-1.5.1.js:23993
Ember.merge.insertElement ember-1.5.1.js:24944
Ember.View.Ember.CoreView.extend._insertElement ember-1.5.1.js:23921
DeferredActionQueues.flush ember-1.5.1.js:6125
Backburner.end ember-1.5.1.js:6215
Backburner.run ember-1.5.1.js:6254
executeTimers ember-1.5.1.js:6552
(anonymous function)
Removing the line contractItems: [1, 2] resolves this, but obviously the related objects are not loaded then.
I thought, I did something wrong with camelcasing and tried different versions, but no success.
Ember is used in version 1.5.1, Ember-Data in version 1.0.0-beta9.
Any hints are welcome...

You're relationships will need to be defined as async since they aren't loaded in the same payload as the record you are loading.
App.Contract = DS.Model.extend({
contractItems: DS.hasMany('contractItem', {async:true}),
//
});
App.ContractItem = DS.Model.extend({
contract: DS.belongsTo('contract', {async:true}),
//
});
Remember when accessing async properties to use then
contract.get('contractItems').then(function(items){
console.log(items.get('length'));
});

Related

EmberJS Mirage 404 error on get /rentals

I'm following tutorial on this page (https://guides.emberjs.com/v2.7.0/tutorial/installing-addons/) until the next tutorial page. (Actually I follow until finished the tutorial.)
Everything seems to working fine. ✔
Ember server is serving and display in the browser correctly. ✔
Ember development build also display correctly. ✔
But Ember production build give me /rentals 404 error. ✖
How to fix this 404 error on production build?
Here is my mirage/config.js
export default function() {
// These comments are here to help you get started. Feel free to delete them.
/*
Config (with defaults).
Note: these only affect routes defined *after* them!
*/
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
// this.namespace = ''; // make this `api`, for example, if your API is namespaced
// this.timing = 400; // delay for each request, automatically set to 0 during testing
/*
Shorthand cheatsheet:
this.get('/posts');
this.post('/posts');
this.get('/posts/:id');
this.put('/posts/:id'); // or this.patch
this.del('/posts/:id');
http://www.ember-cli-mirage.com/docs/v0.2.x/shorthands/
*/
this.get('/rentals', function(db, request) {
let rentals = [{
type: 'rentals',
id: 1,
attributes: {
title: 'Grand Old Mansion',
owner: 'Veruca Salt',
city: 'San Francisco',
type: 'Estate',
bedrooms: 15,
image: 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Crane_estate_(5).jpg'
}
}, {
type: 'rentals',
id: 2,
attributes: {
title: 'Urban Living',
owner: 'Mike Teavee',
city: 'Seattle',
type: 'Condo',
bedrooms: 1,
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Alfonso_13_Highrise_Tegucigalpa.jpg'
}
}, {
type: 'rentals',
id: 3,
attributes: {
title: 'Downtown Charm',
owner: 'Violet Beauregarde',
city: 'Portland',
type: 'Apartment',
bedrooms: 3,
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Wheeldon_Apartment_Building_-_Portland_Oregon.jpg'
}
}];
if(request.queryParams.city !== undefined) {
let filteredRentals = rentals.filter(function(i) {
return i.attributes.city.toLowerCase().indexOf(request.queryParams.city.toLowerCase()) !== -1;
});
return { data: filteredRentals };
} else {
return { data: rentals };
}
});
}
The url prefix and namespace don't change anything, still /rentals 404 error.
GET http://localhost/rentals 404 Not Found
"NetworkError: 404 Not Found - http://localhost/rentals"
Error while processing route: index Ember Data Request GET /rentals returned a 404
ember-cli-mirage is disabled in production build, you should explicitly enable it in config:
if (environment === 'production') {
ENV['ember-cli-mirage'] = {
enabled: true
};
}
Mirage Documentation
The docs have been updated to include a fix for this issue.
Now if you go to the section in the docs called Setting up Application Tests to use Mirage you will see it says to open /tests/acceptance/list-rentals-test.js and insert in this import statements at the top:
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
Then in tests/acceptance/list-rentals-test.js and add a setupMirage(hooks); right after setupApplicationTest(hooks)
module('Acceptance | list rentals', function(hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
...
}
Then the data and the tests will pass.

Error returning promise from Ember Data

I am working on my first Ember app and got it to display the way I wanted with the route returning a static JSON object from model():
element: {
name: "First Element",
divisions: [{
name: "First Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}, {
name: "Second Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}]
}
Now I am trying to refactor to use Ember Data + Mirage and having an awful time.
Here’s my index.js route
export default Ember.Route.extend({
model() {
return this.store.find('element', 1);
},
If I set up my Mirage config.js like this:
this.get('/elements', function() {
return {
elements: [
{
id: 1,
name: 'First Element',
divisions: [1, 2]
}
]
}
});
then I get this error:
Your Ember app tried to GET '/elements/1', but there was no route defined to handle this request.
If I set up my Mirage config.js like this:
this.get('/elements/1', function() {
return {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
});
then I get this error:
22:46:40.883 "Error while processing route: index" "Assertion Failed: normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta"." "EmberError#http://localhost:4200/assets/vendor.js:25582:15
EDIT:
So this isn't a solution to the problem as stated but it got me past this. I gave up on Pretender and started again creating an actual Rails server according to this excellent tutorial: http://emberigniter.com/modern-bridge-ember-and-rails-5-with-json-api/
I was able to do everything I wanted this way and if I ever want to make this a production app, I'm a lot closer.
So the issue is that you aren't actually adhering to the JSON API specification. You can solve this by reading Mirage's page on how to conform.
Essentially you need to either be returning an object at the top level of your JSON response in the case of a GET /foo/1 call. You'll also need to change your "elements" attribute to "data" for GET /foo and that should do the trick. Right now there isn't a simple, re-usable way to do this Mirage out of the box. The best bet right now for both issues is to use the solution presented in this issue.
ember error normalizeResponse must return a valid JSON API document
can be fixed in three ways
return a valid JSONAPI response
see your error message:
normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta".
this.get('/elements/1', function() {
return {
data: {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
}
});
see also https://jsonapi.org/examples/
normalize all responses
// app/serializers/application.js
import EmberData from "ember-data";
export default EmberData.JSONAPISerializer.extend({
normalizeResponse() {
return {
data: this._super(...arguments),
};
},
//normalize(){},
//serialize(){},
// ...
});
problem: error handling
by wrapping all responses in { data: ... }, they never return errors
on errors, the response should be
this.get('/elements/1', function() {
return {
errors: [
{
id: 12345,
title: 'title for error #12345'
}
]
}
});
see also https://jsonapi.org/format/#error-objects
replace JSONAPI with REST
sed -i 's/JSONAPISerializer/RESTSerializer/g' app/serializers/*.js
sed -i 's/JSONAPIAdapter/RESTAdapter/g' app/adapters/*.js
ember docs: adapters and serializers
duplicate: How can ember application be integrated to use with json-server?

http-mock naming conventions

I've setup a http-mock route using Ember CLI with the following command:
ember g http-mock exercise-templates
Which then sets up the file exercise-templates.js which is defined as:
module.exports = function(app) {
var express = require('express');
var exerciseTemplatesRouter = express.Router();
exerciseTemplatesRouter.get('/', function(req, res) {
res.send({
"exercise-templates":[
{id: 1, name: 'Military Press', type: 'strength', muscles: [] },
{id: 2, name: 'Situps', type: 'strength', muscles: [] },
{id: 3, name: 'Yoga', type: 'class', muscles: [] },
{id: 4, name: 'Pilattes', type: 'class', muscles: [] }
]
});
});
app.use('/api/exercise-templates', exerciseTemplatesRouter);
};
So, when I then point the browser to http://localhost:4200/api/exercise-templates I was expecting to get my static JSON response defined above. Instead I get a 404. Then to my surprise I typed in http://localhost:4200/api/exercise-template (aka, without the 's') and it worked. Huh? Makes me wonder what is going on ... I mean I'm no Express guru but doesn't:
app.use('/api/exercise-templates', exerciseTemplatesRouter);
imply that the plural naming convention will be used?
Ok well the answer turns out to be ... turn off "ember serve" and restart. Not sure why it wasn't refreshing but apparently the mocking does not always (ever?) gracefully refresh when updated. In any event, my expectation about "naming convention" appears to be the naming convention so I can happily report that all is right in the world again.

Can not access properties of model object with an error saying "Cannot redefine property: name" in a Ember handlebar template

In a ember template, my model.partners is an array of objects and I tried to iterate and print all name properties but I got an error saying "Cannot redefine property: name"
{{#each partner in model.partners}}
<li>
{{partner.name}}
</li>
{{/each}}
---> I got an error saying "Cannot redefine property: name"
So I tried {{log partner}} helper to see if each partner object is correct, it show correct object information including name property.
{{#each partner in model.partners}}
<li>
{{log partner}}
</li>
{{/each}}
----> This iteration print all information of model.partners correctly
Here is my Ember environment information.
DEBUG: -------------------------------
DEBUG: Ember : 1.4.0
DEBUG: Ember Data : 1.0.0-beta.7.f87cba88
DEBUG: Handlebars : 1.1.2
DEBUG: jQuery : 2.0.3
DEBUG: -------------------------------
Ember Inspector ($E): Object {userInfo: Object, partners: (...),__ember1395345243022_meta: Meta}
What could be an issue here?
Any help will be much appreciated.
-Edit
I am just wondering what the error message means "Can not redefine propery:" and who is complaining this.
This is the log from the Ember Inspector when I got the error using {{partner.name}}, you can see Ember.watchKey is the top of the stack
Transitioned into 'landing' libs.js:6215
Transition #0: TRANSITION COMPLETE. libs.js:6215
Uncaught TypeError: Cannot redefine property: name libs.js:6595
Ember.watchKey libs.js:6595
Ember.watch libs.js:7114
Ember.addObserver libs.js:8386
Ember.View.Ember.CoreView.extend.registerObserver libs.js:27048
simpleBind libs.js:30930
bindHelper libs.js:31030
(anonymous function) libs.js:30978
program1 templates.js:130
prog libs.js:475
Ember.View.Ember.CoreView.extend.render libs.js:26009
Ember.CoreView.Ember.Object.extend._renderToBuffer libs.js:24947
Ember.View.Ember.CoreView.extend._renderToBuffer libs.js:26578
superWrapper
The following log is the one I got when I was successful to see partner objects through console using {{log partner}}, you can see 7 partner objects in the Ember Inspector. Please understand blurring out actual names for privacy reason.
Transitioned into 'landing' libs.js:6215
Transition #0: TRANSITION COMPLETE. libs.js:6215
Object {value: 0, name: "ASM", idx: 0} libs.js:6215
Object {value: 1, name: "Air Force", idx: 1} libs.js:6215
Object {value: 2, name: "Army", idx: 2} libs.js:6215
Object {value: 3, name: "Coast Guard", idx: 3} libs.js:6215
Object {value: 4, name: "Marines", idx: 4} libs.js:6215
Object {value: 5, name: "Navy", idx: 5} libs.js:6215
Object {value: 6, name: "Wives", idx: 6} libs.js:6215
Would you guide me how/where to start debugging this issue? I have a plenty of time for this and let me know any help you need from me.
Thanks.
Have you tried writing the loop like this?
{{#each model.partners}}
<li>
{{name}}
</li>
{{/each}}
In side the each block the this is the model in the array that is being looped over. so oyu could write it {{this.name}} but the this is inplied so it can be removed.
I finally resolved this issue.
I used the following codes in the model hook when I got the error.
model: function() {
return new Ember.RSVP.Promise(function(resolve) {
...
// JSON data from the server
//{"userInfo":{"uid":0,"username":"","isRegistered":0,"email":""}, "partners":[{"value":0,"name":"ASM","idx":0},{"value":1,"name":....}...]}
var retObj = {'userInfo':userInfo,'partners':partners};
resolve(retObj);
...
});
},
What I needed to do was cloning the retObj variable above before calling resolve(...).
Please see the codes below for details.
I think, this is due to the fact that the retObj object has the userInfo variable as an Object type and the partners as an Array type so I should have not used the retObj directly.
model: function() {
return new Ember.RSVP.Promise(function(resolve) {
...
// JSON data from the server
//{"userInfo":{"uid":0,"username":"","isRegistered":0,"email":""}, "partners":[{"value":0,"name":"ASM","idx":0},{"value":1,"name":....}...]}
var retObj = {'userInfo':userInfo,'partners':partners};
var newRetObj = jQuery.extend(true, {}, retObj);
resolve(newRetObj);
...
});
},
Cloning the retObj using jQuery.extend() resolves the error saying "Uncaught TypeError: Cannot redefine property:*".
Thanks again for all who've tried to help me out for this issue and Please feel free to comment more if you think there are something I missed.

Traversing a complex RESTful output (version 12)

I'm getting following (simplified) output from a RESTful API:
{products: [{
product: {
id: 1, name: "T-Shirt red"
},
images: [{
id: 1, size: 'm', url: 'http://db.co/t-shirt-red_m.jpg'
}, {
id: 2, size: 'xl', url: 'http://db.co/t-shirt-red_xl.jpg'
}]
}, {
product: {
id: 2, name: "T-Shirt blue"
},
images: [{
id: 3, size: 'm', url: 'http://db.co/t-shirt-blue_m.jpg'
}, {
id: 4, size: 'xl', url: 'http://db.co/t-shirt-blue_xl.jpg'
}]
}]}
Using Ember version 12, how should the declaration of the Product model looks like and how can I traverse the results? Haven't been able to find any example in that direction.
Following to access the data doesn't work (I just can't find the right syntax):
var products = App.Product.find(); // seems to work
var prodNames = products.getEach('product.name'); // doesn't work
var secondProd = products.getObject(1).get('name'); // doesn't work
Thanks a lot in advance!
claudio.
DS.hasMany and some options for the REST adapter may help you.
I've used a similar setup with MongoDB embedded models. I've attached some examples below.
I didn't want to try to save to the embedded array, so I've used embedded:load, but you can use embedded: 'always' to persist the total object back to the server (although it didn't work quite as I expected) with 'always' if you save the parent object.
DS.RESTAdapter.map 'App.Check',
line_items: { embedded: 'load' }
parties: { embedded: 'load' }
App.Check = DS.Model.extend
description: DS.attr("string")
modified_date: DS.attr("date")
parties: DS.hasMany('App.Party')
App.Party = DS.Model.extend
name: DS.attr("string")
check: DS.belongsTo('App.Party')
You can then reference the item. In a view, I've accessed it as below from a ArrayController where the content is set to an instance of DS.Check.
{{#each party in content.parties }}