I'm doing a model named person and i use parse.com javascript api. To send model to parse.com ì've created a my function send but i think it is wrong. I think that i have to override sync method with api parse.com and after use save method on the model created. It's right?
var Person = Backbone.Model.extend({
defaults: {},
initialize:function() {
console.log("inperson");
},
validate:function() {
console.log("validate");
},
send:function() {
var user = new Parse.User();
user.set("username", this.get("username"));
user.set("password", this.get("password"));
user.set("email", this.get("email"));
user.signUp(null, {
success: function(user) {
},
error: function(user, error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
});
return Person;
});
Backbone only uses one sync method (Backbone.sync). All methods collections and models that are "talking" with the server goes through this one.
You can simply overwrite it by saying:
Backbone.sync = function(method, model, options) {
// method is send through methodMap witch is an object:
//var methodMap = {
// 'create': 'POST',
// 'update': 'PUT',
// 'patch': 'PATCH',
// 'delete': 'DELETE',
// 'read': 'GET'
//};
// model refers to the active model and you can use model.attributes to get all the attributes.
// So in here you can write your integration with parse.com and not change anything else while using backbone.
// Remember to trigger `sync` etc.
};
But I can see that parse.com allready have a REST-api so maybe this is not the solution.
Related
I'm having troubles catching a response from Rails controller upon saving a model. I can see that the XHR response is generated in the Network tab of Chrome's devtools, but success or error functions don't fire. I suspect that this is a consequences of forcing post method and different url directly in the view, but I'm not sure, maybe I've messed up some syntax. Here's the snippet of the the save function in coffee:
save: (user_id) =>
model = #model
if $(".task").val()
#$el.find(".task").each ->
model.set
body: #value
user_id: user_id
task_title_id: model.id
return
model.save null, type: 'post', url: '/tasks',
success: (model, response) ->
console.log 'tasks saved!'
error: (model, response) ->
console.log "error! ", response.responseText
else
console.log 'nothing to save'
and compiled JS:
save = function(user_id) {
var model;
model = this.model;
if ($(".task").val()) {
this.$el.find(".task").each(function() {
model.set({
body: this.value,
user_id: user_id,
task_title_id: model.id
});
});
return model.save(null, {
type: 'post',
url: '/tasks'
}, {
success: function(model, response) {
return console.log('tasks saved!');
},
error: function(model, response) {
return console.log("error! ", response.responseText);
}
});
} else {
return console.log('nothing to save');
}
};
Trivia: I have to generate a new Task view for each existing TasktTitle and then submit these new Tasks to the server. Being very new to the Backbone I couldn't come up with a better idea other than render TaskTitles collection and add input field for each TaskTitle view and then force post method and /tasks url on save. It does feel quite dirty, but it works as expected with the exception of catching the response, which is a crucial part because there is more logic happens on success\error.
This is basically what the original problem reduces to:
I have a Backbone model and I want to execute a certain action every time it saved successfully, but not after it's fetched. The cleanest and least intrusive way to do this, as I see it, would be to attach a handler to the sync event and check the XHR object: if it's a response to a GET, do one thing, and another if it was a POST.
However, looks like I cannot determine the HTTP method the jqXHR was created in response to... or can I?
You can override the Backbone.sync method like this :
var sync = Backbone.sync;
Backbone.sync = function(method, model, options) { // override the Backbone sync
// override the success callback if it exists
var success = options.success;
options.success = function(resp) {
if (success) success(model, resp, options);
// trigger the event that you want
model.trigger(methodMap[method]);
};
sync.call(this, method, model, options);
};
methodMap looks like :
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
}
So in order to catch the GET/POST method all you have to do is :
initialize: function() { // your view initialize
this.listenTo(this.model, "GET", /* your GET callback */);
this.listenTo(this.model, "POST", /* your POST callback */);
}
You can override the save method to do whatever you want; something like this:
#MyApp.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class Entities.Model extends Backbone.Model
save: (data, options = {}) ->
## do whatever you need to do ##
super data, options
Then just extend your models from this definition instead of Backbone.Model, like so:
class Entities.MyModel extends App.Entities.Model
I am trying to update a user object using the JS-SDK but I am getting Duplicate key for schema error. What is the correct way to update a user object using StackMob JS-SDK? Below is my code
var Usr = StackMob.Model.extend({schemaName: 'user'});
var rid = window.localStorage.getItem("devicetoken");
var usr = new Usr({ username: rid });
usr.set({sendnotification: true });
usr.save({
success: function(model, result, options) { console.log('saved'); },
error: function(model, result, options) {console.debug('failed:'+result.error);}
});
Figured out the answer, you need to use the User object directly. There is no need to extend the model
var user = new StackMob.User({ username: rid, sendnotification: true});
user.save({
success: function(model, result, options) { console.log('saved'); },
error: function(model, result, options) {console.debug('failed:'+result.error);}
});
I'm trying to implement authentication with Devise (an authentication gem for Rails) using Backbone. Users can sign out of Backbone by sending the DELETE request to /users/sign_out/ so I couldn't get this link to work because if I click it it's a GET request
<li>sign out</li>
I then created a logout method on the User model, but to trigger it I have to have an instance of the user model (obviously). I created a logout method in the router that gets triggered by navigating to the logout route, but since I can only call logout on the user model with an instance of it, I'm creating a new model in the logout method just to call logout.
"logout": "logout"
},
logout: function(){
var foo = new app.Models.User
foo.logout();
}
This is obviously a bad idea but I don't know what else to do. Can you recommend what I should be doing instead? Is there a way to make the logout a class method so I don't have to instantiate a new model just to logout or something else?
Update
This is the createUser method in the User model that sends the registration data to devise. In the success callback, it assigns the session to a variable window.app.current_user = userSession;. I also have a logout method on the user model that I try to call from the router like this
logout in router
logout: function(){
window.app.current_user.logout();
}
--
app.Models.User = Backbone.Model.extend({
initialize:function () {
},
createUser: function() {
var user = {};
user['email'] = this.get("email");
user['password'] = this.get("password");
user['password_confirmation'] = this.get("password_confirmation");
var registration = {};
registration['user'] = user;
var _this = this;
$.ajax({
url: '/users.json',
type: "POST",
data: {user: user, registration: registration},
success: function(userSession, response) {
window.app.current_user = userSession;
},
... code ommitted
logout: function(){
var me;
console.log("Logging out...");
me = this;
return $.ajax({
url: '/users/sign_out',
type: "DELETE",
dataType: "json",
success: function(data, textStatus, jqXHR) {
window.app.current_user = '';
},
error: function(jqXHR, textStatus, errorThrown) {
return alert("Error logging out: " + errorThrown);
}
});
},
I am slightly confused why you would want to trigger a logout function when the User model has not already been created. Could you please explain your reasoning behind having this logout function in your router?
Personally, I would have a Session model which listens to the click event of your link. This will then call a logout method which will make the DELETE request.
UPDATE
Here is a quick JsFiddle which shows creating a model and attaching it to a global variable:
http://jsfiddle.net/Francium123/eBG3E/2/
var User = Backbone.Model.extend({
initialize:function () {
this.name = "MyName";
this.password = "password"
},
login:function(){
console.log("login called");
},
logout: function(){
console.log("logout called");
}
});
window.MyModels = window.MyModels || {};
window.MyModels.User = new User();
console.log(window.MyModels.User.login());
console.log(window.MyModels.User.logout());
Please note that this is just an example, I doubt you would want to store the password in the model!
Additionally you should be able to use Backbone Models fetch(GET), save(POST/PUT), destroy(DELETE) methods instead of writing ajax requests directly in the model. If needs be you can override the models sync method.
Is it possible to pass inside the options of the "save" method - a diffrent url/path for the request ?
The default urlRot for the model is --> urlRoot: "/users"
is it possible to do something like that:
this.model.save({
'userName': $('#userName').val(),
'password': $('#password').val()},{
url: "/users/login",
success: function(model, response, options) {
},
So the request, this time, will be sent to "/users/login" and NOT to "/users" ?
From the documentation:
urlmodel.url()
Returns the relative URL where the model's resource
would be located on the server. If your models are located somewhere
else, override this method with the correct logic. Generates URLs of
the form: "/[collection.url]/[id]", falling back to "/[urlRoot]/id" if
the model is not part of a collection.
So it looks as if you can provide your own url function on a model.
Example:
var MyModel = Backbone.Model.extend({
use_custom_url: false,
url: function() {
if (use_custom_url) {
return "/users/login";
} else {
return Backbone.Model.prototype.url.apply(this);
}
}
});