Rendering views for each model in a backbone collection

I'm working on a toy backbone.js application, a library application to perform CRUD operations on a library. Here is the book model and the library collection (of books)

var Book = Backbone.Model.extend({
    url: function() {
        return '/api/books' + this.get('id');
    }
});

var Library = Backbone.Collection.extend({
    model : Book,
    url : '/api/books'
});

This seems pretty straightforward. Next, I obviously want to be able to show the book, so I have a BookView...

var BookView = Backbone.View.extend({
    tagName: 'li',
    render: function() {
        this.$el.html(this.model.get('author'));
        $('#list-of-books').append(this.$el);
    }
});

all the render method does is append an li to the end of an unordered list with an id of list-of-books that is in my html.

Next, unsurprisingly, if I add the following code, I get a list with one item (the name of the author of the book with id=4)

var a_book = new Book();
a_book.url = '/api/books/4';
a_book.fetch({
    success: function() {
        var bookView = new BookView({ model: a_book });
        bookView.render();
    }
});

Here's where I don't understand. I add the following code and nothing happens:

var some_books = new Library();
some_books.fetch();
some_books.forEach(function(book) {
    alert('why is this function not being run');
    var view = new BookView({ model: book });
    view.render();
});

For some reason, I can't even get that loop code to run, I don't even see that alert pop out to the screen. Let me know if you understand what's wrong with this code and how I can make the list render properly. Thanks

You are calling .render inside fetch. Hence the execution stops over there itself. For loop wont run after fetch as it has returned already.

.fetch() is an asynchronous call, so you may not have the collection data populated when you are calling .forEach().

You should either call the rendering code in the success callback or (even better) render the view on events (reset,...) on the collection.

BTW, you have a typo in the url() function:

url: function() {
    return '/api/books/' + this.get('id');
}

Why are you defining the url function for the Book?, since you use the model attribute in the Library collection, url for the Book will be set correctly by default.