Подтвердить что ты не робот

Backbone.js Модельный URL для создания и обновления?

говорит, что у меня есть модель Backbone, и я создаю экземпляр модели следующим образом:

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

Интересно, если это возможно, когда я использую John.save() для таргетинга /user/create, когда я использую John.save() во второй раз (update/PUT) для таргетинга /user/update, когда я использую John.fetch() для таргетинга /user/get и когда я использую John.remove() для таргетинга /user/remove

Я знаю, что каждый раз могу определить John.url, прежде чем запускать какой-либо метод, но мне интересно, может ли это быть автоматически каким-то образом, без переопределения какого-либо метода Backbone.

Я знаю, что могу использовать один URL-адрес, например /user/handle, и обрабатывать запрос на основе метода запроса (GET/POST/PUT/DELETE), но мне просто интересно, есть ли способ иметь разные URL-адреса для каждого действия в Backbone.

Спасибо!

4b9b3361

Ответ 1

Методы .fetch(), .save() и .destroy() в Backbone.Model проверяют, определена ли модель .sync(), и если да, то она будет вызвана иначе Backbone.sync() будет вызвана (см. последние строки связанного исходного кода).

Итак, одним из решений является реализация метода .sync().

Пример:

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

Ответ 2

Чтобы абстрагировать решение dzejkej на одном уровне, вы можете обернуть функцию Backbone.sync, чтобы запросить модель для URL-адресов, специфичных для метода.

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

Затем вы можете определить модель с помощью:

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

Ответ 3

Вы имеете дело с реализацией REST, которая не соответствует спецификации или нуждается в каком-то обходном пути?

Вместо этого рассмотрите возможность использования опции emulateHTTP, найденной здесь:

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

В противном случае вам, вероятно, просто нужно будет переопределить метод Backbone.sync по умолчанию, и вам будет хорошо идти, если вы хотите сходить с ума от этого... но я не предлагаю этого. Было бы лучше всего использовать истинный интерфейс RESTful.

Ответ 4

Нет, вы не можете сделать это по умолчанию с помощью магистрали. Вы могли бы добавить к модели, которая изменит URL-адрес модели на каждое событие триггера модели. Но тогда у вас всегда есть проблема, что bckbone будет использовать POST добавить первый раз, когда модель была сохранена, и PUT для каждого вызова после этого. Поэтому вам необходимо переопределить метод save() или Backbone.sync.

В конце концов, это не рекомендуется делать, потому что он разбивает шаблон REST, на котором построена базовая панель.

Ответ 5

Я получил вдохновение от этого решения, где вы просто создаете свой собственный вызов ajax для методов, которые не предназначены для выборки модели. Вот отредактированная версия:

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;

И тогда вы можете использовать его следующим образом:

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