2012-09-10 31 views
6

Tôi nghĩ rằng tôi có một vấn đề khá đơn giản, khá khó để từ và do đó khó tìm được giải pháp cho. Setup:Truyền/khởi tạo các mô hình con của Mô hình xương sống

  • PathCollection là một Backbone.Collection của Paths
  • Đường dẫn là một Backbone.Model chứa NodeCollection (mà là một Backbone.Collection) và EdgeCollection (mà là một Backbone.Collection).

Khi tôi lấy PathCollection

paths = new PathCollection() 
paths.fetch() 

rõ ràng, Paths được khởi tạo. Tuy nhiên, tôi đang thiếu vị trí mà tôi có thể cho phép một đường dẫn để khởi tạo submodels của nó từ băm thuộc tính. Tôi không thể sử dụng phân tích cú pháp, đúng không? Về cơ bản im tìm kiếm điểm vào cho một mô hình khi nó được khởi tạo và thiết lập với các thuộc tính. Tôi cảm thấy như phải có một số quy ước cho nó.

+1

Bạn đã thử sử dụng phương pháp [initialize] (http://documentcloud.github.com/backbone/#Model-constructor) chưa? – Jack

+0

nó sẽ hoạt động khi tôi khởi tạo Bộ sưu tập, nhưng nếu tôi tự tìm nạp Đường dẫn thì sao? Khi tôi sẽ lấy Path, tôi đã intialized, phải không? – nambrot

+0

Để đưa ra một từ cho điều này, tôi nghĩ rằng những gì bạn muốn làm là đọc thêm về "mô hình lồng ghép và bộ sưu tập". – jmk2142

Trả lời

24

Vì vậy, tôi đã viết một vài câu trả lời về việc sử dụng parse()set() để khởi tạo và điền các mô hình phụ và các tập hợp con (dữ liệu lồng nhau). Tuy nhiên, tôi đã không nhìn thấy một câu trả lời thực sự toàn diện mà củng cố một số trong nhiều thực hành tôi đã nhìn thấy. Tôi có xu hướng xáo trộn một chút khi tôi viết rất nhiều vì vậy tôi có thể digress một chút nhưng điều này có thể hữu ích cho những người đi qua các loại tương tự của các vấn đề.

Có một số cách để thực hiện việc này. Sử dụng parse() là một. Thao tác set() là một cách khác. Việc khởi tạo chúng trong số initialize() là một số khác. Làm tất cả bên ngoài mô hình Đường dẫn là mô hình khác (ví dụ: path = new Path(); path.nodes = new NodeCollection();, v.v.)

Xem xét thứ hai là điều này. Bạn có muốn các nút và các bộ sưu tập cạnh là các thuộc tính mô hình không? Hoặc mô hình tài sản?

Rất nhiều lựa chọn. Rất nhiều tự do nhưng đôi khi (với sự thất vọng của chúng tôi) nó làm cho nó khó khăn hơn để xác định "đúng cách."

Vì điều này xảy ra thường xuyên, tôi sẽ tạo một bài đăng dài và thực hiện từng bước một. Vì vậy, chịu với tôi khi tôi tiếp tục cập nhật câu trả lời này.

Làm nó bên ngoài của các mô hình - đơn giản và thẳng về phía trước

này thường là một cách dễ dàng để thêm các mô hình lồng nhau và các bộ sưu tập khi bạn chỉ cần nó trên một mô hình hoặc bộ sưu tập đặc biệt.

path = new PathModel(); 

path.nodes = new NodeCollection(); 
path.edge = new EdgeCollection(); 

// Continue to set up the nested data URL, etc. 

Đây là cách đơn giản nhất và hoạt động tốt khi bạn đang xử lý một mô hình thời gian và bộ sưu tập không cần phải có định nghĩa. Mặc dù bạn có thể dễ dàng sản xuất các mô hình này theo một số phương pháp (ví dụ: phương pháp xem) để tạo đối tượng này trước khi thực hiện bất kỳ thứ gì với nó.

Sử dụng initialize() Sub-mô hình/bộ sưu tập trong mỗi mô hình

Nếu bạn biết rằng tất cả các thể hiện của một mô hình nào đó sẽ luôn luôn có một tiểu mô hình hoặc phụ thu, cách dễ nhất để thiết lập những điều sẽ sử dụng chức năng initialize().

Ví dụ, có mô hình con đường của bạn:

Path = Backbone.Model.extend({ 
    initialize: function() { 
     this.nodes = new NodeCollection(); 
     this.paths = new PathCollection(); 

     // Maybe assign a proper url in relation to this Path model 
     // You might even set up a change:id listener to set the url when this 
     // model gets an id, assuming it doesn't have one at start. 
     this.nodes.url = this.id ? 'path/' + this.id + '/nodes' : undefined; 
     this.paths.url = this.id ? 'path/' + this.id + '/paths' : undefined; 
    } 
}); 

Bây giờ tiểu bộ sưu tập của bạn có thể được lấy như path.nodes.fetch() và nó sẽ định tuyến đến URL chính xác. Dễ như ăn bánh.

Sử dụng parse() cho instantiating và thiết lập tiểu dữ liệu

Có lẽ, nó được khéo léo hơn một chút nếu bạn không muốn đảm nhận tất cả các mô hình được sẽ có một nút và các bộ sưu tập cạnh. Có thể bạn chỉ muốn các mô hình/bộ sưu tập lồng nhau nếu fetch() gửi lại dữ liệu đó. Đây là trường hợp sử dụng parse() có thể hữu ích.

Điều với parse() là phải mất bất kỳ phản hồi máy chủ json nào và có thể đúng không gian tên và xử lý nó trước khi chuyển nó đến hàm set() mô hình. Vì vậy, chúng tôi có thể kiểm tra xem liệu một mô hình hoặc dữ liệu thô thu thập được bao gồm và xử lý nó trước khi giảm phản hồi xuống các thuộc tính mô hình gốc.

Ví dụ, có thể từ máy chủ của chúng tôi, chúng tôi nhận được phản ứng này:

// Path model JSON example with nested collections JSON arrays 
{ 
    'name':'orange site', 
    'url':'orange.com', 
    'nodes':[ 
     {'id':'1', 'nodeColor':'red'}, 
     {'id':'2', 'nodeColor':'white'}, 
     {'id':'3', 'nodeColor':'blue'} 
    ], 
    'edge':[ 
     {'id':'1', 'location':'north'}, 
     {'id':'1', 'location':'south'}, 
     {'id':'1', 'location':'east'} 
    ] 
} 

Với mặc định parse() Backbone sẽ gobble này lên và gán mô hình đường dẫn của bạn thuộc tính 'nút' và 'cạnh' với một mảng() dữ liệu (không phải bộ sưu tập.) Vì vậy, chúng tôi muốn đảm bảo rằng các giao dịch parse() của chúng tôi phù hợp với điều này một cách thích hợp.

parse: function(response) { 

    // Check if response includes some nested collection data... our case 'nodes' 
    if (_.has(response, 'nodes')){ 

     // Check if this model has a property called nodes 
     if (!_.has(this, 'nodes')) { // It does not... 
      // So instantiate a collection and pass in raw data 
      this.nodes = new NodeCollection(response.nodes); 
     } else { 
      // It does, so just reset the collection 
      this.nodes.reset(response.nodes); 
     } 

     // Assuming the fetch gets this model id 
     this.nodes.url = 'path/' + response.id + '/nodes'; // Set model relative URL 

     // Delete the nodes so it doesn't clutter our model attributes 
     delete response.nodes; 
    } 

    // Same for edge... 

    return response; 
} 

Bạn cũng có thể sử dụng tùy chỉnh set() để xử lý dữ liệu phụ của mình. Sau nhiều lần chuyển qua lại giữa chúng tốt hơn, hãy thao tác set() hoặc thực hiện nó trong parse() Tôi đã quyết định rằng tôi muốn sử dụng parse() hơn. Nhưng tôi cởi mở với suy nghĩ của người khác về điều này.

Sử dụng set() để đối phó với tiểu dữ liệu của bạn

Trong khi parse() dựa trên một trong hai lấy dữ liệu hoặc thông qua dữ liệu vào một bộ sưu tập với các tùy chọn parse:true một số người thấy nó ưu đãi để thay đổi set() chức năng. Một lần nữa, tôi không chắc chắn có một sự lựa chọn chính xác nhưng đây là cách mà sẽ làm việc.

set: function(attributes, options) { 
    // If we pass in nodes collection JSON array and this model has a nodes attribute 
    // Assume we already set it as a collection 
    if (_.has(attributes, 'nodes') && this.get("nodes")) { 
     this.get('nodes').reset(attributes.nodes); 
     delete attributes.nodes; 
    } else if (_.has(attributes, 'nodes') && !this.get('nodes')) { 
     this.set('nodes', new NodeCollection(attributes.nodes)); 
     delete attributes.nodes; 
    } 

    return Backbone.Model.prototype.set.call(this, attributes, options); 
} 

Vì vậy, nếu chúng ta đã có một thuộc tính và nó là một bộ sưu tập, chúng tôi reset() nó. Nếu chúng ta có một thuộc tính nhưng nó không phải là một bộ sưu tập, chúng ta khởi tạo nó. Điều quan trọng là phải đảm bảo bạn dịch đúng các mảng JSON của dữ liệu phụ thành một bộ sưu tập trước khi bạn chuyển nó vào mẫu thử nghiệm set(). Backbone, không giải thích mảng JSON như một bộ sưu tập và bạn sẽ chỉ nhận được một mảng thẳng.

Vì vậy, trong vỏ hạt, bạn có nhiều tùy chọn về cách thực hiện. Một lần nữa, hiện tại tôi ủng hộ kết hợp sử dụng initialize() khi tôi biết điều gì đó sẽ luôn có các mô hình/bộ sưu tập phụ và parse() khi tình huống chỉ gọi cho dữ liệu lồng nhau có thể có trên các cuộc gọi fetch().

Về câu hỏi đó của bạn ...(Oh yeah, có một câu hỏi)

Bạn có thể cho phép Đường dẫn khởi tạo mô hình phụ từ một hàm băm theo nhiều cách khác nhau. Tôi chỉ cho bạn 4. Bạn CÓ THỂ sử dụng phân tích cú pháp nếu bạn muốn, nếu bạn biết bạn sẽ là fetch() mô hình đường dẫn HOẶC thậm chí có thể là một pathCollection ... pathCollection.fetch({parse:true}) Có quy ước nào không? Co le không. Tôi thích sử dụng kết hợp các cách tùy thuộc vào ngữ cảnh trong đó tôi nghĩ tôi sẽ sử dụng các mô hình/bộ sưu tập.

Tôi rất cởi mở để thảo luận về một số thực tiễn này và liệu chúng có tốt hay xấu. Họ chỉ là nhiều giải pháp tôi đã gặp trên Stack và kết hợp vào thói quen làm việc của riêng tôi và họ dường như làm việc tốt cho tôi. :-)

Tự uống cà phê và vỗ nhẹ ở mặt sau, đã được đọc lâu.

Các vấn đề liên quan