Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you don't mind, I'm going to start with clearing up some wording. REST is not a protocol in itself, it's simply a way of using the HTTP protocol. The REST style is especially useful for APIs, as I hope you'll see. When an API conforms to that style, it is said to be "RESTful". If the API you're working with isn't RESTful, you'll have to make a lot of changes to Backbone.sync in order to get it to work. So hopefully it is! :)</p> <h2>The HTTP Protocol</h2> <p>I like examples, so here is an HTTP request to get the HTML for this page:</p> <pre><code>GET /questions/18504235/understand-backbone-js-rest-calls HTTP/1.1 Host: stackoverflow.com </code></pre> <p>[Optional] If you have ever played with command line or terminal, try running the command <code>telnet stackoverflow.com 80</code> and pasting in the above, followed by pressing enter a couple of times. Voila! HTML in all of it's glory.</p> <p>In this example...</p> <ul> <li><code>GET</code> is the <strong>method</strong>.</li> <li><code>/questions/18504235/understand-backbone-js-rest-calls</code> is the <strong>path</strong>.</li> <li><code>HTTP/1.1</code> is the <strong>protocol</strong>.</li> <li><code>Host: stackoverflow.com</code> is an example of a <strong>header</strong>.</li> </ul> <p>Your browser does approximately the same, just with more headers, in order to get the HTML for this page. Cool, huh?</p> <p>Since you work in front end, you've probably seen the form tag many times. Here's an example of one:</p> <pre><code>&lt;form action="/login" method="post"&gt; &lt;input type="text" name="username" /&gt; &lt;input type="password" name="password" /&gt; &lt;input type="submit" name="submit" value="Log In" /&gt; &lt;/form&gt; </code></pre> <p>When you submit this form along with appropriate data, your browser sends a request that looks something like this:</p> <pre><code>POST /login HTTP/1.1 Host: stackoverflow.com username=testndtv&amp;password=zachrabbitisawesome123&amp;submit=Log%20In </code></pre> <p>There are three differences between the previous example and this one.</p> <ol> <li>The <strong>method</strong> is now <code>POST</code>.</li> <li>The <strong>path</strong> is now <code>/login</code>.</li> <li>There is an extra line, called the <strong>body</strong>.</li> </ol> <p>While there are a bunch of other methods, the ones used in RESTful applications are <code>POST</code>, <code>GET</code>, <code>PUT</code>, and <code>DELETE</code>. This tells the server what type of action it's supposed to take with the data, without having to have different paths for everything.</p> <h2>Back to Backbone</h2> <p>So hopefully now you understand a bit more about how HTTP works. But how does this relate to Backbone? Let's find out!</p> <p>Here's a small chunk of code you might find in a Backbone application.</p> <pre><code>var BookModel = Backbone.Model.extend({ urlRoot: '/books' }); var BookCollection = Backbone.Collection.extend({ model: BookModel , url: '/books' }); </code></pre> <h3>Create (POST)</h3> <p>Since we're using a RESTful API, that's all the information Backbone needs to be able to create, read, update, and delete all of our book information! Let's start by making a new book. The following code should suffice:</p> <pre><code>var brandNewBook = new BookModel({ title: '1984', author: 'George Orwel' }); brandNewBook.save(); </code></pre> <p>Backbone realizes you're trying to <strong>create</strong> a new book, and knows from the information it's been given to make the following request:</p> <pre><code>POST /books HTTP/1.1 Host: example.com {"title":"1984","author":"George Orwel"} </code></pre> <h3>Read (GET)</h3> <p>See how easy that was? But we want to get that information back at some point. Let's say we ran <code>new BookCollection().fetch()</code>. Backbone would understand that you're trying to <strong>read</strong> a <strong>collection</strong> of books, and it would make the following request:</p> <pre><code>GET /books HTTP/1.1 Host: example.com </code></pre> <p>BAM. That easy. But say we only wanted the information for one book. Let's say book #42. Say we ran <code>new BookModel({ id: 42 }).fetch()</code>. Backbone sees you're trying to <strong>read</strong> a <strong>single</strong> book:</p> <pre><code>GET /books/42 HTTP/1.1 Host: example.com </code></pre> <h3>Update (PUT)</h3> <p>Oh darn, I just realized I spelled Mr. Orwell's name wrong. Easy to fix!</p> <pre><code>brandNewBook.set('author', 'George Orwell'); brandNewBook.save(); </code></pre> <p>Backbone is smart enough to know that despite being called <code>brandNewBook</code>, it's already been saved. So it <strong>updates</strong> the book:</p> <pre><code>PUT /books/84 HTTP/1.1 Host: example.com {"title":"1984","author":"George Orwell"} </code></pre> <h3>Delete (DELETE)</h3> <p>Finally, you realize that the government is tracking your every move, and you need to bury the fact that you have read 1984. It's probably too late, but it never hurts to try. So you run <code>brandNewBook.destroy()</code>, and Backbone <strike>becomes sentient and realizes your danger</strike> <strong>deletes</strong> the book with the following request:</p> <pre><code>DELETE /books/84 HTTP/1.1 Host: example.com </code></pre> <p>And it's gone.</p> <h2>Other Useful Tidbits</h2> <p>While we've talked a lot about what we're sending TO the server, we should probably also take a look at what we're getting back. Let's return to our collection of books. If you remember, we made a <code>GET</code> request to <code>/books</code>. In theory, we should get back something like this:</p> <pre><code>[ {"id":42,"author":"Douglas Adams","title":"The Hitchhiker's Guide to the Galaxy"} , {"id":3,"author":"J. R. R. Tolkien","title":"The Lord of the Rings: The Fellowship of the Ring"} ] </code></pre> <p>Nothing too scary. And even better, Backbone knows how to handle this out of the box. But what if we changed it a bit? Instead of <code>id</code> being the identifying field, it was <code>bookId</code>?</p> <pre><code>[ {"bookId":42,"author":"Douglas Adams","title":"The Hitchhiker's Guide to the Galaxy"} , {"bookId":3,"author":"J. R. R. Tolkien","title":"The Lord of the Rings: The Fellowship of the Ring"} ] </code></pre> <p>Backbone gets that every API is a bit different, and it's okay with that. All you have to do is let it know the <code>idAttribute</code>, like so:</p> <pre><code>var BookModel = Backbone.Model.extend({ urlRoot: '/books' , idAttribute: 'bookId' }); </code></pre> <p>You only have to add that information to the model, since the collection checks the model anyway. So just like that, Backbone understands your API! <em>Even if I don't...</em></p> <p>The downside of this is that you have to remember to use <code>bookId</code> in certain cases. For example, where we previously used <code>new BookModel({ id: 42 }).fetch()</code> to load the data about a single book, we would now have to use <code>new BookModel({ bookId: 42 }).fetch()</code>.</p> <hr> <p>Hopefully you've found this response informative, and not too unbearably dull. I realize that for many, HTTP protocol and RESTful architecture aren't the most exhilarating subjects, so I tried to spice it up a bit. I may regret that when I read all of this back at a later point, but it's 2AM here, so I'm gonna go ahead and submit this anyway.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload