Ember.js model save sends no data to server - javascript

I'm currently building a small demo app using Ember.JS and NodeJS with Express. I've knocked up a simple model and have created an action to save it.
The component has a property called recipe, which is an instance of a model I've defined. The save action is as simple as:
save() {
this.get('recipe').save();
}
Looking at my network tab in Chrome dev tools, I can see the data in the request payload. However, I can't access the data in my Node app. I've logged the full req object and my data isn't there anywhere.
I have a feeling this is to do with the fact that Ember uses the PATCH verb, whereas I'd expect it to use PUT or POST.
Any help is greatly appreciated.

Disclaimer: Without seeing the code it is difficult to give you a definitive answer.
The JSON API specification defines, that updating a resource is done with the PATCH verb. (http://jsonapi.org/format/#crud-updating)
If you chose to use this adapter, you will have to define the appropriate routes in your Express app. Without seeing it, I'd suggest to define the route for PUT and PATCH with the same callback and you'll be fine.
For example:
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
Overriding the HTTP verb in the adapter is not that easy at the moment (Ember Data 2.4). A possible head would be to override the updateRecord method of the adapter. (https://github.com/emberjs/data/blob/v2.4.0/addon/adapters/json-api.js#L115-L133)

Disclaimer: Without seeing the code it is difficult to give you a definitive answer.
You're not receiving the request payload because the 'Content-Type' header has not been set properly.
The JSONAPIAdapter for Ember sends requests with the 'Content-Type' header set to 'application/vnd.api+json'. You'll need to set this in body-parser like so:
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));

In the end, I fixed the issue by using DS.RESTAdapter as opposed to DS.JSONAPIAdapter. The RESTAdapter uses PUT when you save a record while JSONAPIAdapter uses PATCH. I suspect there's some issue in the implementation of PATCH in either Ember or Express.

Related

React ES6 App - Local API calls

I can't for the life of me figure this out, it seems like it should be straight forward but it's just not clicking.
I have an ES6 app that I created using create-react-app. I've got all the templates and layouts set up for the project and came to trying to pull in data from an API that I want to sit inside the app - like a botched MVC where React handles the views and I run the models and controllers in PHP.
So I have a function in one of my components that I want to fetch some data. I use the fetch() function (I know this isn't yet compatible with a number of browsers but that's a problem for another day) to fetch a relative path from the component to the model I want to load, however the fetch function treats my path as a call to the base URL followed by the request. So with the site running on localhost:3000, I run the following code in my getData() function...
let test = fetch('../models/overall-stats.php').then(function(response) {
console.log(response);
return response;
});
...the URL that fetch hits is then http://localhost:3000/models/overall-stats.php which simply resolves back to the index.html file and loads the app, rather than the PHP file I'm requesting.
If I need to hit that PHP file to get my data, am I wrong in using fetch? Or am I just using it incorrectly? If I shouldn't be using fetch what's a better approach to this problem I'm having?
When I run this on an apache server (after building and deploying) I can get the fetches to work fine (apache recognizes the structure of the URL and hits it as I am expecting) and I hit the file no issues, but I need to be able to work in a local development environment and have the same functionality. The app will end up being deployed live on an apache server.
Any help would be greatly appreciated.
I knew after sleeping on this it would be very straight-forward... I simply had to move my models and controllers into the public directory for them to be accessible. I'll be putting in authentication to the models so that they can't be hit directly, but only through GET requests.
Why don't you just use something like ${baseUrl}/models/... ?
Also for solving browsers problem with fetch you can import the Polyfill or simply use axios (my choice)!
Maybe you can try to use ajax to get or post the data from server, just like this:
$.ajax({
url: '../models/overall-stats.php',
data: {
},
type: 'GET',
dataType : 'json',
success : function(res){
let obj = parseJSON(res)
}
})
or add this on top in your php file because the CORS :
header('Access-Control-Allow-Origin: *');

How to bypass an express middleware?

I'm working with an express application. There are some express routes, as
server.get('*' , ... )
etc. which perform some common operations: authentication, validation... etc.
they also decorates the response with meaningful information: i.e. in every request to the server it gives not only the expected json/html, but also information regarding the user, some app metadata that the front-end consumes etc. etc.
Let's say all this extra metadata cames in a field called extradata in every request to the server.
Now, there is a bug that is causing a problem: instead of returning its expected response (a json with a bunch of system logs), is sending only this extradata field.
I'm pretty confident the problem is in one of the middlewares, because that code that sends the response in this case is really simple, it's just a res.send() of a json. So I believe this part of the app is requiring some module that sets a middleware which causes the error. There are a lot of global vars and implicit parameters in the app so is really difficult to debug it manualluy.
I attempted to bypass such middlewares programmatically, like:
delete server._router.stack[2];
but is causing an TypeError: Cannot read property 'route' of undefined and thus preventing my app to build: sure this is not the way to go.
so, is there a way to programmatically ignore or bypass express routes that are yet set?
Even better, is there a way to programmatically tap into express middlewares and log every request and response?
(afaik, there are libreries like morgan that logs every request, but I don't think they apply to this case since I need to discriminate between middlewares).
What I generally do is simply use the next method. You can access it by simply passing it to the callback function. Something like:
app.use(function(req, res, next) {
if(...) {
next();
} else {
...
}
}
What this is going to do is go to the next middleware.
So if I understand correctly, you can check what you exactly need in the if-statement and do things accordingly.
What I would suggest is you read the Express API documentation, especially the section about middleware, which you can find here. Moreover, try to isolate the suspects and solve the issue by removing the problem, rather than deleting handlers and trying to solve the problem the easy way.

Mirage `passthrough` is not working

I'm trying to use passthrough for a POST request in this Ember project
this.passthrough('/thirdeye/entity?entityType=ANOMALY_FUNCTION');
This is what the call looks like in app/mirage/config.js.
I got the following error:
Mirage: Your Ember app tried to POST '/thirdeye/entity?entityType=ANOMALY_FUNCTION',
but there was no route defined to handle this request.
Define a route that matches this path in your
mirage/config.js file. Did you forget to add your namespace?
Clearly, I've added that call to the config file, but it's not being picked up. I read that passthrough only works for >= jquery 2.x, which my project is.
Does anyone know what else could cause this?
I found out the problem was I had to do this.passthrough('/thirdeye/***'); since the call has query params. It works now.

Phonegap will not delete data from mongodb (mongolab)

I have built a small phonegap app in backbone.js which connects to a mongodb backend(hosted on mongolab) I can successfully retrieve and add to collections using the following url in my Backbone.Collection:
url: 'https://api.mongolab.com/api/1/databases/site_manager/collections/items?apiKey=****************'
but when I try to delete a model from the collection it does not remove it from the db. I have set the urlRoot of my model with an /:id attribute:
urlRoot : 'https://api.mongolab.com/api/1/databases/site_manager/collections/items/:id?apiKey=**********************'
but it still doesn't seem to be working - I'm not sure if i've put the id attribute in the right place. Everything works locally with a local server/db so I'm sure it has to do with the URL. Can anyone help with this please?
I am aware of security risks of accessing my db directly from the clientside with the API key but htis is just for a quick prototype.
Thanks
Have you tried to use Fiddler or
other tool that will allow you to monitor the HTTP requests and the returned status code that your application makes? At least you will be able to define where is problem.

Saving backbone model on parse.com

i can save a model on parse.com writing:
var persona=new Person({username:"filiberto",password:"filiberto"});
persona.save( {
success: function (persona) {
console.log("modello salvato nel db");
console.log(persona.url());
}
});
but if i first fetch a collection,get a specified model and update by save method doesn't work and error is:PUT https://api.parse.com/1/classes/_User/V742NGMTjA 400 (Bad Request)
Models.utenti = new Usercollection();
Models.utenti.fetch({async:false});
var current_user=Models.utenti.get(Parse.User.current().id);
current_user.set_last_activity();
current_user.save();<----PUT https://api.parse.com/1/classes/_User/V742NGMTjA 400 (Bad
Request)
I've tried to update another class on parse.com and works. The class that i can't update is users,maybe a security reason?
I'm unfamiliar with Parse, but according to their API (https://www.parse.com/docs/rest#users), a users request should be a POST not a PUT. Backbone uses PUT to update/sync models, whereas POST is used to create new models. The issue might be that Backbone is assuming that your model has already been saved and using the PUT method to update it.
Parse has a nice tutorial demonstrating the users API with Backbone (https://parse.com/tutorials/todo-app-with-javascript). You might also find this discussion addressing saving vs updating Backbone models helpful (Backbone model.save() is sending PUT instead of POST).
UPDATE: It appears that Parse requires Cross-Origin Resource Sharing (CORS) to modify existing users' data. In practice, this means adding additional information in the request header. See Parse's blog post in the comments below for more info and implementation details.

Categories