disons que j'ai un modèle Backbone et que je crée une instance d'un modèle comme celui-ci:
var User = Backbone.Model.extend({ ... });
var John = new User({ name : 'John', age : 33 });
Je me demande s'il est possible lorsque j'utilise John.save()
de cibler /user/create
lorsque j'utilise John.save()
une deuxième fois (update/PUT) sur /user/update
cible lorsque j'utilise John.fetch()
pour cibler /user/get
et lorsque j'utilise John.remove()
pour cibler /user/remove
Je sais que je pourrais définir John.url
chaque fois avant de déclencher une méthode, mais je me demande si cela pourrait se produire automatiquement sans modifier la méthode Backbone.
Je sais que je pourrais utiliser une URL telle que /user/handle
et gérer la requête en fonction de la méthode de requête (GET/POST/PUT/DELETE), mais je me demande s’il existe un moyen d’avoir une URL différente par action dans Backbone.
Merci!
Méthodes .fetch()
, .save()
et .destroy()
on Backbone.Model
vérifie si le modèle a défini .sync()
et si oui, il sera appelé sinon Backbone.sync()
sera appelé (voir les dernières lignes du code source lié ).
Une des solutions consiste donc à implémenter la méthode .sync()
.
Exemple:
var User = Backbone.Model.extend({
// ...
methodToURL: {
'read': '/user/get',
'create': '/user/create',
'update': '/user/update',
'delete': '/user/remove'
},
sync: function(method, model, options) {
options = options || {};
options.url = model.methodToURL[method.toLowerCase()];
return Backbone.sync.apply(this, arguments);
}
}
Pour résumer dzejkej} solution d'un niveau, vous pouvez envelopper la fonction Backbone.sync
pour interroger le modèle sur URL spécifiques à une méthode.
function setDefaultUrlOptionByMethod(syncFunc)
return function sync (method, model, options) {
options = options || {};
if (!options.url)
options.url = _.result(model, method + 'Url'); // Let Backbone.sync handle model.url fallback value
return syncFunc.call(this, method, model, options);
}
}
Ensuite, vous pouvez définir le modèle avec:
var User = Backbone.Model.extend({
sync: setDefaultUrlOptionByMethod(Backbone.sync),
readUrl: '/user/get',
createUrl: '/user/create',
updateUrl: '/user/update',
deleteUrl: '/user/delete'
});
Avez-vous affaire à une implémentation REST non spécifiée ou nécessitant une solution de contournement?
Pensez plutôt à utiliser l'option emulateHTTP
trouvée ici:
http://documentcloud.github.com/backbone/#Sync
Sinon, vous devrez probablement simplement remplacer la méthode par défaut Backbone.sync
et vous pourrez continuer si vous voulez devenir vraiment fou avec ça ... mais je ne le suggère pas. Il serait préférable d'utiliser simplement une véritable interface RESTful.
Non, vous ne pouvez pas faire cela par défaut avec le réseau fédérateur. Ce que vous pouvez faire est d’ajouter au modèle qui modifiera l’URL du modèle à chaque événement déclenché par le modèle. Mais vous avez toujours le problème que bckbone utilisera POST
ajouter la première fois que le modèle a été enregistré et PUT
pour chaque appel suivant. Vous devez donc également remplacer la méthode save()
ou Backbone.sync
.
Après tout, il semble que ce ne soit pas une bonne idée de le faire, car cela brise le modèle REST
sur lequel Backbone est construit.
Je me suis inspiré de this solution, où vous créez simplement votre propre appel ajax pour les méthodes qui ne permettent pas d’extraire le modèle. En voici une version allégée:
var Backbone = require("backbone");
var $ = require("jquery");
var _ = require("underscore");
function _request(url, method, data, callback) {
$.ajax({
url: url,
contentType: "application/json",
dataType: "json",
type: method,
data: JSON.stringify( data ),
success: function (response) {
if ( !response.error ) {
if ( callback && _.isFunction(callback.success) ) {
callback.success(response);
}
} else {
if ( callback && _.isFunction(callback.error) ) {
callback.error(response);
}
}
},
error: function(mod, response){
if ( callback && _.isFunction(callback.error) ) {
callback.error(response);
}
}
});
}
var User = Backbone.Model.extend({
initialize: function() {
_.bindAll(this, "login", "logout", "signup");
},
login: function (data, callback) {
_request("api/auth/login", "POST", data, callback);
},
logout: function (callback) {
if (this.isLoggedIn()) {
_request("api/auth/logout", "GET", null, callback);
}
},
signup: function (data, callback) {
_request(url, "POST", data, callback);
},
url: "api/auth/user"
});
module.exports = User;
Et ensuite, vous pouvez l'utiliser comme ceci:
var user = new User();
// user signup
user.signup(data, {
success: function (response) {
// signup success
}
});
// user login
user.login(data, {
success: function (response) {
// login success
}
});
// user logout
user.login({
success: function (response) {
// logout success
}
});
// fetch user details
user.fetch({
success: function () {
// logged in, go to home
window.location.hash = "";
},
error: function () {
// logged out, go to signin
window.location.hash = "signin";
}
});