I've been working on a Backbone.js project that syncs to a Google App Engine REST server I've also put together. I'm using the Appengine-Rest-Server project code to enable the REST interface. IT works really well, but there is one problem. When I post a new model to it, it expects a JSON post in the form of:
{ 'modelname' : {'attribute1':'attribute','attribute2':'attribute'}}
When I use python and the requests library to POST this data to my REST server... it works fine.
Backbone.js appears to be sending POST requests without the model name a la
{'attribute1':'attribute','attribute2':'attribute'}
Now, not being an expert on what formats are 100% RESTful, I'm not sure whether my REST server is improperly configured (in which case I don't expect you guys to be able to help with the code), whether Backbone.js is improperly configured, or whether both formats are potentially RESTful and I just need to figure out how to get backbone to add in the model name.
So, to close, is one or both of these formats compatible with a truly RESTful API? If requiring the model name in the JSON is not a gross violation of making a RESTful API, does anyone know how I can make Backbone send out post requests in the proper format?
Thanks!
Most elegant way:
YourModel = Backbone.Model.extend({
name: 'modelName',
toJSON: function () {
var data = {};
data[this.name] = _.clone(this.attributes); // or Backbone.Model.prototype.toJSON.apply(this)
return data;
}
});
Or you can directly pass data to the options
model.save(null, {
data: {
// custom format
}
});
Related
P.S I probably didn't quite understand the mvc principle, but I always thought that business logic should happen in models - correct me if I'm wrong
I am writing project and using the mvc pattern.
router accepts requests and passes to controller, it takes data and sends it to model. Model checks the data for validation and, if successful, works with the database. My models have very large code and mix with validation.
exports.modelFunction = (data) => {
// validation data ...
// working with the database
}
With new fixes it becomes difficult for me to read the code.
I decided to create a utils / validation / folder where I will handle all possible model validations and yes, now the code is more readable
exports.modelFunction = (data) => {
const validation = validationModel(data);
if (!validation) return {ok: false, message: 'Validation failed'}
// working with the database
}
I thought that there are already some other patterns that adhere to the separation of logic and solve problems like mine. So I decided to ask you for a hint.
I think you're confused with data validation with business logic.
The controller is where your business logic lives. It it is the gateway to allow for model access.
If the controller decides that the user can access/modify the data, then it passes that data down to your model to do work.
Your model should validate the data and see if it has all the required attributes to work with the database. If it doesn't then it fails and is returned to your controller. If that happens, then your controller needs to do your business logic and respond back to the request with the status.
I have application built on Ember.js (2.13). I have User model and at this moment I work on avatar upload feature. When I modify model and save it then Ember makes PATCH request to my API during it Ember serializer builds nice json-api object and I like it.
When I need to upload image to server I need to make some PUT request to my API with file data I could use jQuery ajax for this. Server will resize and crop image and save it on disk or push it to S3 bucket. But I do not like this way because this request will be created bypassing Ember's serializer and without references to model. So I need to set uploaded filename to User model and save it then I'll have redundant request to server.
I have an idea to transform file to base64 string in Ember.js app and set this string to User model and save it. In this case I'll have one request to server. Is this good way to upload file?
Please advice best practice of uploading files in Ember.js application.
But I do not like this way because this request will be created
bypassing Ember's serializer and without references to model.
There is nothing you can do about this - ember data does not support files. And in many situations ED is not good enough (for example - nested resource URIs, partial updates). I suggest to not be bothered about it too much - if your can't perform some request using ember data, just use Ember.$.ajax.
So I need to set uploaded filename to User model and save it then I'll
have redundant request to server.
No, you don't. Just configure your backend to return full user model (as you do for other get/post/update requests which use ED), and pass result (if request was successful, of course) to pushPayload method of the store. Store will be updated with actual data without additional requests. Example:
this.get('session').authorize('authorizer:token', (headerName, headerValue) => {
const headers = {};
headers[headerName] = headerValue;
/*Instead of data object, you will create a formData*/
const data = {
/*Some data*/
};
Ember.$.ajax(
{
url: '/path-to-resource/id-of-resource',
headers,
type: "PUT",
data
}
)
.then(
(payload) => {
this.store.pushPayload(payload);
},
(response) => {
this.set('errorMessage', stringifyError(response));
}
)
.always(() => {
this.set('isLoading', false);
});
});
UPD: There is an addon, ember-cli-form-data which claims to add support of file upload to ember data. I didn't try it myself, so can't say if it works and how good.
You can give it try using popular ember addon for this.
ember-plupload and ember-uploader addon
The Short
I have an existing WCF Data Service that I would like to wire up to use in an AngularJS SPA using Breeze.
Can anyone show a noobie level example of how to do that with out access to the actual database (just the OData Service)?
The Long
I have an existing WCF Data Service that is already in use by a WPF app.
I experimenting with web development and would like to wire up to that service using Breeze. In case it matters, I am using Angular (and am setting up via the HotTowel.Angular nuget package).
I have done a fair amount of Googling and I am stuck.
I can see two ways outlined from my searching:
The First
Make is to make a Breeze controller on the server side of my web app.
The problem I see with that is the metadata. From my limited understanding I need to tell breeze all the meta data of my WCF Data Service. I know how to get the meta from my WCF Data Service (the url + $Metadata), but I don't know how to tell this to Breeze.
The Second
This way is more vague in implementation. I got it from the accepted answer on this question: Breeze.js with WCF Data Service.
Basically the answer here does not seem to work. It relies on something called the entityModel that I cannot seem to find (I have an entityManager, but not an entityModel. And the entityManager does not have the properties that the entityModel is shown to have.
In the end I like the idea of the second method best. That way I can directly connect to my odata service with out needed my web app to have a "in-between" server component. But I would happily take anything that does not need entity framework to connect to my database.
I tried several variations of the second option, but I just can't seem to get it to work. I also tried the Breeze samples. It has one for OData, but it still relies on having Entity Framework hook up to the source database.
To to clearly summarize what I am asking: I am looking for a Breeze example that connects to an existing WCF Data Service.
We regret that you were mislead by that old StackOverflow answer which was way out of date and (therefore) incorrect. There is no longer a type called entityModel.
I updated the answer there and repeat here the same advice.
The recommended way to configure Breeze so that it talks to a standard OData source (such as a WCF OData service) is
breeze.config.initializeAdapterInstance('dataService', 'OData', true);
Here's how you might proceed with defining an EntityManager and querying the service:
// specify the absolute URL to the WCF service address
var serviceName = "http://localhost:9009/ODataService.svc";
var em = new breeze.EntityManager(serviceName);
var query = breeze.EntityQuery.from("Customers")
.where("CompanyName", "startsWith", "B")
.orderBy("City");
em.executeQuery(query).then(function(data) {
// process the data.results here.
});
There is some documentation on this subject here.
A Web API OData service differs from a WCF OData service in several respects. But you may still find value in the Angular Web API OData sample.
I'm developing extension to an existing app using expressjs. By requirements I need to do server side rendering. Our API server is running on JAVA.
In my express app, I'm going to have to render page while making serverside calls to JAVA server. For example, I'm going to call getCategories, getVendors, getReviews etc APIs in order get data that I need to pass to rendering template.
What is a good way to accomplish this? I mean pack all of that into a single object and pass to res.render() method. Could you please provide me with some basic examples? I imagine that I would need to create a module that does all of this and returns some nice object...
All of the examples on the internet show something like res.render('index', { data: 'someData'}), however in this case data is bootstrapped. I would need a data to be compiled with several API calls and then passed to the rendering method.
Thanks!
It really depends on whether you want to call your Java API server side or client side.
If server side, your express route containing res.render() will need to collect all the information it needs from Java before rendering the page. If your API is slow, the page load will be slow. If possible, use something like async.parallel to avoid blocking.
Your code sample is correct. res.render('index', { foo: 'bar'})
This would add the foo variable to the root scope of your view. How you build up the data structure is entirely up to you. I would recommend using async.parallel and/or async.series to collate all of the data. If they are all completely independent, run them in parallel.
// an example of how to run each in parallel and then render the view.
var getCategories = function(done) {
// get something
done();
};
var data = {};
async.parallel([
getCategories, // <-- adds to the data structure
getVendors,
getReviews
], function(err) {
res.render('index', { data: data });
});
Your other option is using express to render the base page and using something like jQuery to hit the Java API and update the relevant page fragments.
I had no issues hooking up breeze to querying the azure mobile services rest endpoints however I was not able to figure out how to perform an update/insert.
Doing something like this works great except for the save part.
var datas = new breeze.DataService({
hasServerMetadata: false,
serviceName: serviceName // my endpoint
});
var manager = new breeze.EntityManager({ dataService: datas });
// manager.enableSaveQueuing(true);
var qu = breeze.EntityQuery.from("notification").where("id", "==", 1);
manager.executeQuery(qu).then(function (data) {
data.results[0].isRead = false;
console.log(manager.hasChanges());
manager.saveChanges();
});
How can we use breezejs with the azure mobile service to either insert or update records.
I can see that you're not getting metadata from the service (you set hasServerMetadata: false) and you aren't defining any metadata on the client. Therefore you have an empty BreezeJS entity model which means that every query returns raw JavaScript objects not Breeze entities.
These raw objects are not in cache, they are not change tracked, they don't have any property change notification or binding support. They are just data.
manager.hasChanges() will always be false and manager.saveChanges() won't do anything ... because you never have any entities.
I haven't tried Breeze with AMS (aka "ZUMO") yet and don't know much about it. I'm sure that it will work with Breeze. But someone has to put in some time to discover how to get metadata from the server, how to insert/update/delete, and how ZUMO data flow over the wire.
My understanding is that ZUMO objects are flat objects that map directly to SQL Azure tables. They have no associations with other entities/tables and that you have to manage foreign keys and related-entity loads by hand. It's really not ready for the rich object models typical of business applications.
For the moment, I suggest you stick with ZUMO's own client component for accessing data.
We'll have a Breeze story in due time.