ember-cli - Ember Data get request failed TypeError - undefined is not a function - coffeescript

I'm porting the ember portion of an ember-rails app to Ember CLI. So far so good, but I'm having trouble with a get request that's blowing up in RESTSerializer.
The Application Controller attempts to grab a list of widgets
`import Ember from 'ember'`
ApplicationController = Ember.Controller.extend
widgets: (->
#store.find('unfinishedWidgets', id: #get('currentId'))
).property()
`export default ApplicationController`
I can see the API Request fire off, the JSON comes back, everything looks just like it did in the Ember Rails stack. Except then instead of updating the property and displaying in the view, it blows up:
TypeError: undefined is not a function
at Object.func (http://localhost:4200/myapp/assets/vendor.js:49473:18)
at Object.Cache.get (http://localhost:4200/myapp/assets/vendor.js:25091:38)
at decamelize (http://localhost:4200/myapp/assets/vendor.js:49515:31)
at RESTSerializer.extend.keyForAttribute (http://localhost:4200/myapp/assets/vendor.js:66565:16)
at apply (http://localhost:4200/myapp/assets/vendor.js:32821:27)
at superWrapper [as keyForAttribute] (http://localhost:4200/myapp/assets/vendor.js:32393:15)
at null.<anonymous> (http://localhost:4200/myapp/assets/vendor.js:69024:31)
at null.<anonymous> (http://localhost:4200/myapp/assets/vendor.js:71513:20)
at cb (http://localhost:4200/myapp/assets/vendor.js:29067:22)
at OrderedSet.forEach (http://localhost:4200/myapp/assets/vendor.js:28865:13) vendor.js:28532logToConsole vendor.js:28532RSVP.onerrorDefault vendor.js:42608__exports__.default.trigger vendor.js:61072Promise._onerror vendor.js:62084publishRejection vendor.js:60315(anonymous function) vendor.js:42583DeferredActionQueues.invoke vendor.js:13853DeferredActionQueues.flush vendor.js:13923Backburner.end vendor.js:13309Backburner.run vendor.js:13364run vendor.js:31375hash.success vendor.js:68006fire vendor.js:3237self.fireWith vendor.js:3349done vendor.js:9393callback
I put in a breakpoint at decamelize, which stopped so I could inspect what was going on:
function decamelize(str) {
return DECAMELIZE_CACHE.get(str);
}
str at this point isn't a string, it's:
Object {type: undefined, isAttribute: true, options: Object, parentType: function, name: "bundleId"}
isAttribute: true
name: "otherId"
options: Object
parentType: (subclass of DS.Model)
type: undefined__proto__: Object
So this is the first DS.attr() in my Model:
`import DS from 'ember-data'`
unfinishedWidgets = DS.Model.extend
otherId: DS.attr()
# other attrs
`export default UnsubmittedRequest`
I'm using a ActiveModelAdapter by default, and I've also made an empty ActiveModelSerializer.
`import DS from 'ember-data'`
ApplicationAdapter = DS.ActiveModelAdapter.extend
namespace: 'api/myapp/v1'
`export default ApplicationAdapter`
`import DS from 'ember-data'`
ApplicationSerializer = DS.ActiveModelSerializer.extend()
`export default ApplicationSerializer`
EDIT:
I ended up fixing it with:
ApplicationSerializer = DS.ActiveModelSerializer.extend
keyForAttribute: (type, name) ->
name
Though I'm still not clear on why it was necessary in Ember CLI when it was fine in Ember-rails

This happens when your server returns an invalid json response. In this case it's not returning with a root object.
You're server is likely returning something like this
{
other_id: 1
// ...
}
and it needs to be
{
unfinished_widget: {
other_id: 1
// ...
}
}
The ActiveModelAdapter/Serializer expects it in that style. Honestly this error is terrible and should be reported as a bug in ember-data. I've hit it before and it's super hard to debug and track down.

So, as it turns out, it was simply a bug in EmberData 1.0.0.beta.10. I updated to beta 12 and everything worked.

Related

Data return from axios cant be written to variable

I want to get an data attribute from my axios post and write it to an local variable to reuse it.
If i console.log it inside the axios .then, tha data is set, if i write it to my variable and want to use it after, it is empty.
export default {
data(){
return {
post:{},
projectId: '',
existingProjects: []
}
},
methods: {
addPost(){
//check if project exists else create
let uriProj = 'http://localhost:4000/projects/add';
this.axios.post(uriProj, {
projectName: this.post.project,
}).then(response => this.projectId = response.data.data);
console.log("project_id: "+this.projectId)
}
}
What am i doing wrong?
Another Question:
Is this the right way if i want to reuse the id in another method?
My Goal is to first create a project if it is not already in my db, then i want to reuse the id of the created or returned project model to create a new customer in my db, if the customer already has the project with the id of this project, it shouldnt be added, if it is a new one it should be added.
Has this to be done in multiple requests or is there a simple method for doing this?
I believe the issue you are seeing has to do with the asynchronous nature of network calls. When axios submits the post request it returns a Promise then the addPost function continues executing. So the projectId gets logged after it the initial value gets set, but before the network request completes. Everything inside the then() function executes once the network request has been completed so you can test by moving the console.log to be executed once the request is done. You could also output the value in the template so you can see it update {{ projectId }}
this.axios.post(uriProj, {
projectName: this.post.project,
}).then(response => {
this.projectId = response.data.data
console.log("project_id: "+this.projectId)
});
I would ideally recommend using the VueJS dev tools browser extension because it allows you to inspect the state of your Vue components without having to use console.log or add random echos to your template markup.
#jfadich is correct. I recommend using async/await instead of then, it's more intuitive to read.
async addPost(){
//check if project exists else create
let uriProj = 'http://localhost:4000/projects/add';
let resp = await this.axios.post(uriProj, {
projectName: this.post.project,
})
this.projectId = resp.data.data
console.log("project_id: "+this.projectId)
}

Having Trouble Initializing Postgresql Database Through PG-Promise

I'm completely new to Express/Postgresql and I'm trying to learn them to create a web application. After some poking around, I decided that I wanted to develop my back-end with TypeScript. I successfully converted all my other files from JavaScript to TypeScript, but I still can't figure out how to initialize the pg-promise connection in TypeScript!
I've been trying to follow the TypeScript guidelines in this link here. https://github.com/vitaly-t/pg-promise/tree/master/typescript
// Initialize the PostGres database conneciton for use throughout
the entire application
import {IMain, IDatabase} from 'pg-promise';
import * as pgPromise from 'pg-promise';
const pgp: IMain = pgPromise({
query(e: any) {
console.log('QUERY RESULT:', e.query);
},
receive(data: any, result: any, e: any) {
console.log(`DATA FROM QUERY ${e.query} WAS RECEIVED.`);
}
});
const connection: any = {
host: 'localhost',
port: 5432,
database: 'RushHub',
user: 'RyanArifin',
password: null
}
const db: IDatabase<any> = pgp(connection);
export {
db
};
I currently am getting the error "TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof pgPromise' has no compatible call signatures." This error is coming from when I try to set my initialization options. Any help would be appreciated, thanks!
This is standard TypeScript configuration flag - esModuleInterop. When set to true, the import syntax is import pgPromise from 'pg-promise';, and when false, which is the default, the syntax is import * as pgPromise from 'pg-promise';.
The library gives you example for the default TypeScript configuration.

Why am I getting this 'undefined' error?

I'm working on a Meteor project, and for some reason this profile template refuses to work.
I'm using the following code, as well as the accounts-password and accounts-entry packages for user management:
this.route('profile', {
path: '/profile/:username',
data: function() {
var userDoc = Meteor.users.findOne({"username": this.params.username});
var bookCursor = Books.find({owner: userDoc._id});
return {
theUser: userDoc,
theBooks: bookCursor
};
}
});
When I try to go to the profile URL for my test accounts ('misutowolf', and 'test2', respectively), I am given the following error in Chrome's dev console: Exception from Deps recompute function: TypeError: Cannot read property '_id' of undefined, pointing to the use of userDoc._id in the call to Books.find().
This makes no sense whatsoever, as I was able to find a user document with the names in question using meteor mongo with both usernames, in the form db.users.find({username: "misutowolf"}) and db.users.find({username: "test2"}).
I am very confused, not sure what is causing this issue at all.
By default Meteor only publish the currently logged in user info via an automatically setup publication.
What you need to do is push to the client the user info (username) you're trying to use, because if you don't do that, the user you're accessing is not published to the client and you get an undefined error when accessing its _id.
First, setup a dedicated publication (on the server) :
Meteor.publish("userByUsername",function(username){
return Meteor.users.find({
username:username
});
});
Then waitOn this publication in your route :
waitOn:function(){
return this.subscribe("userByUsername",this.params.username);
}
Finally, guard against accessing the user document until it is pushed to the client because even if you are waiting on the subscription, the data method might actually get called even if the subscription is not ready yet.
data: function() {
var userDoc = Meteor.users.findOne({"username": this.params.username});
if(!userDoc){
return;
}
// ...
}

Can't use cache:true with OAuth.initialize

I am trying to use OAuth according to https://oauth.io/docs/api in an android eclipse app.
import io.oauth.*;
.....
final OAuth o = new OAuth(this);
o.initialize(KEY);
works fine.
However, I want to use the cache functionality in order not to log on every time, so I try
o.initialize(KEY, {cache: true});
Unfortunately this won't compile. I get
"Multiple markers at this line
-Syntax error on tokens, delete these tokens
-Syntax error on token(s), misplaced construct(s)"
As you can tell I am an android and Eclipse newbie, any help appreciated.
The public key is the only argument used for the initialize method.
The correct method that accepts the cache object as an argument is popup.
Example:
OAuth.initialize('x9x9x9x9x9'); //OAuth.io public key
var promise = OAuth.popup('google_mail', {cache: true});
promise.done(function (result) {
    // make API calls
});
promise.fail(function (error) {
    // handle errors
});

Ember and Socket.io/Websocket

I'm trying to pull in a livestream of data from a socket.io websocket, coming in as JSON.
I was trying to use the method from these folks, but no luck (I'm getting error - "Uncaught TypeError: Cannot call method 'load' of undefined" - which I haven't been able to figure out on my own):
Socket.IO with Ember and Ember-Data
My code:
var socket = io.connect('http://localhost:8007');
socket.on('my_live_stream', function (data) {
store.load(App.Group, data);
});
And more:
App.Group = DS.Model.extend({
id: DS.attr('string'),
name: DS.attr('string'),
usage: DS.attr('string'),
sunshine: DS.attr('string'),
device_info: DS.attr('string')
});
Edit: What the JSON looks like...
{
"group":{
"usage":{
"case1":0,
"case2":0,
"case3":0
},
"sunshine":"00/00/0000",
"id":1010,
"device_info":11.5,
...
I'm still very new to Ember here, but I'm just trying to get {{name}}, {{usage}}. and {{device_info}} to my Index template. I see a great stream of data when I add console.log(data) to the socket code (to replace store.load...). What's the next step?
Thanks so much!
The question you reference is using a very outdated version of Ember Data. You should pretty much ignore any Stack Overflows from before October.
The new method you want is store.push, in your case, in your case store.push('Group', data).
However, there's yet another problem in your code, which is that you don't have access to store in that context. Normally, you access the store inside routes and controllers via this.store. However, you're not inside a route or controller. If you want, you could hack access to the store like so, store = App.__container__.lookup('store:main'), but this is not the Ember way and will probably cause you problems down the line. Instead, you could add it to one of the hooks in the Application Route, where you do have access to this.store.
For example, you could set it up like this:
App.ApplicationRoute = Ember.Route.extend({
activate: function(){
var that = this;
var socket = io.connect('http://localhost:8007');
socket.on('my_live_stream', function (data) {
that.store.push('Group', data.group);
});
})
});
Docs: http://emberjs.com/guides/models/pushing-records-into-the-store/