2012-01-04 24 views
31

phép nói rằng tôi có một mô hình Backbone và tôi có thể tạo một thể hiện của một mô hình như thế này:Backbone.js Mô hình url khác nhau để tạo và cập nhật?

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

Tôi tự hỏi nếu nó có thể khi tôi sử dụng John.save() để nhắm mục tiêu /user/create khi tôi sử dụng John.save() trên lần thứ hai (cập nhật/PUT) để nhắm mục tiêu /user/update khi tôi sử dụng để nhắm mục tiêu John.fetch()/user/get và khi tôi sử dụng để nhắm mục tiêu John.remove()/user/remove

tôi biết rằng tôi có thể xác định John.url mỗi lần trước khi tôi kích hoạt phương pháp nào nhưng tôi tự hỏi nếu nó có thể được xảy ra autom về cơ bản một số cách mà không ghi đè bất kỳ phương pháp Backbone nào.

Tôi biết rằng tôi có thể sử dụng một url như /user/handle và xử lý yêu cầu dựa trên phương thức yêu cầu (GET/POST/PUT/DELETE) nhưng tôi tự hỏi liệu có cách nào để có url khác nhau cho mỗi hành động trong Backbone hay không .

Cảm ơn!

Trả lời

78

Phương pháp .fetch(), .save().destroy() trên Backbone.Model đang kiểm tra nếu mô hình có .sync() xác định và nếu có nó sẽ được gọi là khác Backbone.sync() sẽ được gọi (xem dòng cuối cùng của mã nguồn liên kết).

Vì vậy, một trong các giải pháp là triển khai phương pháp .sync().

Ví dụ:

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

Giải pháp tốt. Thay vì 'options = options || {}; ', bạn nên sử dụng' tùy chọn || (tùy chọn = {}); 'để tránh việc tái chỉ định không cần thiết. –

+2

@BrianNickel Tôi đồng ý rằng mã của bạn được tối ưu hóa hơn nhưng tôi đã dành chút thời gian để đưa nó vào câu trả lời vì các công cụ JSLint/JSHint đang đánh dấu nó là một vấn đề và theo tôi thì khó đọc hơn ... nhưng tôi đã cho bạn +1 bởi vì nó deservers một sự chú ý :). – kubetz

+0

Cảm ơn rất nhiều dzejkej đã chỉ ra rằng đầu tiên nó sẽ xem xét phương thức đồng bộ của mô hình, tôi đã bỏ lỡ hoàn toàn :) Cảm ơn @Brian Nickel vì đã chỉ ra điều này :) – panosru

0

Không, bạn không thể làm điều này theo mặc định với xương sống. Những gì bạn có thể làm là thêm vào mô hình sẽ thay đổi url mô hình trên mọi sự kiện kích hoạt mô hình. Nhưng sau đó bạn luôn có vấn đề bckbone sẽ sử dụng POST thêm lần đầu tiên mô hình được lưu và PUT cho mọi cuộc gọi sau đó. Vì vậy, bạn cũng cần phải ghi đè phương thức save() hoặc Backbone.sync.

Sau khi tất cả có vẻ như không phải là một ý tưởng tốt để làm điều này gây ra nó phá vỡ các xương sống mô hình REST được xây dựng trên.

+0

Cảm ơn bạn đã trả lời Andrea :) – panosru

1

Bạn đang xử lý việc triển khai REST không phải là để xác định hoặc cần một số cách giải quyết khác?

Thay vào đó, hãy xem xét sử dụng tùy chọn emulateHTTP tìm thấy ở đây:

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

Nếu không, có thể bạn sẽ chỉ cần phải ghi đè phương pháp mặc định Backbone.sync và bạn sẽ được tốt để đi nếu bạn muốn nhận được thực sự điên rồ với điều đó ... nhưng tôi không đề nghị điều đó. Nó sẽ là tốt nhất để chỉ sử dụng một giao diện RESTful thực sự.

+0

Cảm ơn bạn đã trả lời :) Tôi sẽ đưa vào xem xét sau khi thực hiện REST thay vì "hack xung quanh" :) – panosru

2

Để giải pháp trừu tượng dzejkej của một cấp độ cao hơn, bạn có thể quấn Backbone.sync chức năng để truy vấn các mô hình cho URL phương pháp cụ thể.

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

Sau đó, bạn có thể định nghĩa các mô hình với:

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

Tôi đã lấy cảm hứng từ this giải pháp, nơi bạn chỉ cần tạo cuộc gọi ajax của riêng bạn cho các phương pháp mà không phải là cho việc lấy mô hình. Dưới đây là một phiên bản cắt giảm của nó:

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; 

Và sau đó bạn có thể sử dụng nó như thế này:

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"; 
    } 
}); 
Các vấn đề liên quan