2012-01-04 11 views
31

Diciamo che ho un modello Backbone e creo un'istanza di un modello come questo:Backbone.js Crea un URL diverso per la creazione e l'aggiornamento?

var User = Backbone.Model.extend({ ... }); 
var John = new User({ name : 'John', age : 33 }); 

Mi chiedo se è possibile quando uso John.save() per indirizzare /user/create quando uso John.save() sulla seconda volta (aggiornamento/PUT) per indirizzare /user/update quando uso John.fetch() a bersaglio /user/get e quando uso John.remove() di indirizzare /user/remove

so che potrei definire John.url ogni volta prima di innescare qualsiasi metodo, ma mi chiedo se si potesse accadere autom un po 'come senza escludere alcun metodo Backbone.

So che potrei usare un url come /user/handle e gestire la richiesta in base al metodo di richiesta (GET/POST/PUT/DELETE) ma mi chiedo solo se c'è un modo per avere URL diversi per azione in Backbone .

Grazie!

risposta

78

Metodi .fetch(), .save() e .destroy() su Backbone.Model stanno controllando se il modello ha .sync() definito e se sì, in caso contrario verrà chiamato Backbone.sync() verrà chiamato (vedi le ultime righe del codice sorgente collegata).

Quindi una delle soluzioni è implementare il metodo .sync().

Esempio:

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); 
    } 
} 
+13

Buona soluzione. Invece di 'opzioni = opzioni || {}; ', dovresti usare' opzioni || (opzioni = {}); 'per evitare la riassegnazione non necessaria. –

+2

@BrianNickel Sono d'accordo sul fatto che il tuo codice sia più ottimizzato, ma sono un po 'riservato per includerlo nella risposta perché gli strumenti JSLint/JSHint lo segnano come un problema e secondo me è più difficile da leggere ... ma io ti ha dato +1 perché merita un'attenzione :). – kubetz

+0

Grazie mille dzejkej per aver sottolineato che prima guarderà il metodo di sincronizzazione del modello, mi sono perso completamente :) Grazie @Brian Nickel per averlo fatto notare anche :) – panosru

0

No, non è possibile farlo per impostazione predefinita con backbone. È possibile aggiungere al modello che modificherà l'URL del modello su ogni evento che il trigger del modello. Ma poi hai sempre il problema che bckbone userà POST aggiungere la prima volta che il modello è stato salvato e PUT per ogni chiamata successiva. Quindi è necessario sovrascrivere il metodo save() o Backbone.sync.

Dopo tutto, non sembra una buona idea farlo perché interrompe il pattern REST Backbone è costruito.

+0

Grazie per la risposta :) Andrea – panosru

1

Hai a che fare con un'implementazione REST che non è specifica o che richiede una soluzione alternativa?

Invece, è possibile utilizzare l'opzione emulateHTTP trovato qui:

http://documentcloud.github.com/backbone/#Sync

In caso contrario, probabilmente solo bisogno di eseguire l'override del metodo predefinito Backbone.sync e sarete pronti per partire, se si vuole ottenere davvero pazzo di quello ... ma non lo suggerisco. Sarebbe meglio usare solo una vera interfaccia RESTful.

+0

Grazie per la risposta :) mi prendo in considerazione di seguire l'implementazione REST invece di "hacking around" :) – panosru

2

Per soluzione astratta di dzejkej un livello ulteriore, si potrebbe avvolgere la funzione Backbone.sync per interrogare il modello per URL specifici del metodo.

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); 
    } 
} 

Poi si potrebbe definire il modello con:

var User = Backbone.Model.extend({ 
    sync: setDefaultUrlOptionByMethod(Backbone.sync), 
    readUrl: '/user/get', 
    createUrl: '/user/create', 
    updateUrl: '/user/update', 
    deleteUrl: '/user/delete' 
}); 
0

mi sono ispirato da this soluzione, dove basta creare il proprio chiamata AJAX per i metodi che non sono per andare a prendere il modello. Ecco una versione tagliata verso il basso di esso:

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; 

e poi si può usare in questo modo:

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"; 
    } 
}); 
Problemi correlati