I have the following chunk of code. It works perfectly.
<div id="restaurant_locations"></div>
<script type="text/javascript">
$(function() {
window.router = new Lunchhub.Routers.RestaurantLocationsRouter({restaurantLocations: <%= @restaurant_locations.to_json.html_safe -%>});
var Foo = Backbone.Router.extend({routes: {"foo":"bar"}});
r = new Foo();
Backbone.history.start();
});
</script>
However, THIS does NOT work:
<div id="restaurant_locations"></div>
<script type="text/javascript">
$(function() {
window.router = new Lunchhub.Routers.RestaurantLocationsRouter({restaurantLocations: <%= @restaurant_locations.to_json.html_safe -%>});
// All I did was delete the two lines that used to be here
Backbone.history.start();
});
</script>
The latter snippet gives me this error:
Uncaught TypeError: Cannot call method 'start' of undefined
So my Foo router instance triggers a proper initialization of Backbone.history, just like you would expect a router instance to do, but my Lunchhub.Routers.RestaurantLocationsRouter instance does not.
Here’s my router definition in CoffeeScript (generated automatically by the backbone-rails gem):
class Lunchhub.Routers.RestaurantLocationsRouter extends Backbone.Router
initialize: (options) ->
@restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection()
@restaurantLocations.reset options.restaurantLocations
routes:
"new" : "newRestaurantLocation"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
newRestaurantLocation: ->
@view = new Lunchhub.Views.RestaurantLocations.NewView(collection: @restaurant_locations)
$("#restaurant_locations").html(@view.render().el)
index: ->
@view = new Lunchhub.Views.RestaurantLocations.IndexView(restaurant_locations: @restaurant_locations)
$("#restaurant_locations").html(@view.render().el)
show: (id) ->
restaurant_location = @restaurant_locations.get(id)
@view = new Lunchhub.Views.RestaurantLocations.ShowView(model: restaurant_location)
$("#restaurant_locations").html(@view.render().el)
edit: (id) ->
restaurant_location = @restaurant_locations.get(id)
@view = new Lunchhub.Views.RestaurantLocations.EditView(model: restaurant_location)
$("#restaurant_locations").html(@view.render().el)
And here’s the compiled JavaScript:
(function() {
var __hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Lunchhub.Routers.RestaurantLocationsRouter = (function(_super) {
__extends(RestaurantLocationsRouter, _super);
function RestaurantLocationsRouter() {
RestaurantLocationsRouter.__super__.constructor.apply(this, arguments);
}
RestaurantLocationsRouter.prototype.initialize = function(options) {
this.restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection();
return this.restaurantLocations.reset(options.restaurantLocations);
};
RestaurantLocationsRouter.prototype.routes = {
"new": "newRestaurantLocation",
"index": "index",
":id/edit": "edit",
":id": "show",
".*": "index"
};
RestaurantLocationsRouter.prototype.newRestaurantLocation = function() {
this.view = new Lunchhub.Views.RestaurantLocations.NewView({
collection: this.restaurant_locations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.index = function() {
this.view = new Lunchhub.Views.RestaurantLocations.IndexView({
restaurant_locations: this.restaurant_locations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.show = function(id) {
var restaurant_location;
restaurant_location = this.restaurant_locations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.ShowView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.edit = function(id) {
var restaurant_location;
restaurant_location = this.restaurant_locations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.EditView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
return RestaurantLocationsRouter;
})(Backbone.Router);
}).call(this);
What could be going wrong here?
EDIT: I’ve figured out part of the problem. In the CoffeeScript, it was using restaurant_locations in some places where it should have been using restaurantLocations. I’m having a strange problem now, but potentially an easier one: when I copy and paste the compiled JavaScript directly into <script> area, right before the window.router = assignment, everything works perfectly. However, when I try to use the compiled JS as an external file (and I know it’s being included – I checked), I get that same Cannot call method 'start' of undefined error.
Here’s my updated CoffeeScript:
class Lunchhub.Routers.RestaurantLocationsRouter extends Backbone.Router
initialize: (options) ->
@restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection()
@restaurantLocations.reset options.restaurantLocations
routes:
"new" : "newRestaurantLocation"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
newRestaurantLocation: ->
@view = new Lunchhub.Views.RestaurantLocations.NewView(collection: @restaurantLocations)
$("#restaurant_locations").html(@view.render().el)
index: ->
@view = new Lunchhub.Views.RestaurantLocations.IndexView(restaurantLocations: @restaurantLocations)
$("#restaurant_locations").html(@view.render().el)
show: (id) ->
restaurant_location = @restaurantLocations.get(id)
@view = new Lunchhub.Views.RestaurantLocations.ShowView(model: restaurant_location)
$("#restaurant_locations").html(@view.render().el)
edit: (id) ->
restaurant_location = @restaurantLocations.get(id)
@view = new Lunchhub.Views.RestaurantLocations.EditView(model: restaurant_location)
$("#restaurant_locations").html(@view.render().el)
And here’s my updated compiled JavaScript:
(function() {
var __hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
Lunchhub.Routers.RestaurantLocationsRouter = (function(_super) {
__extends(RestaurantLocationsRouter, _super);
function RestaurantLocationsRouter() {
RestaurantLocationsRouter.__super__.constructor.apply(this, arguments);
}
RestaurantLocationsRouter.prototype.initialize = function(options) {
this.restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection();
return this.restaurantLocations.reset(options.restaurantLocations);
};
RestaurantLocationsRouter.prototype.routes = {
"new": "newRestaurantLocation",
"index": "index",
":id/edit": "edit",
":id": "show",
".*": "index"
};
RestaurantLocationsRouter.prototype.newRestaurantLocation = function() {
this.view = new Lunchhub.Views.RestaurantLocations.NewView({
collection: this.restaurantLocations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.index = function() {
this.view = new Lunchhub.Views.RestaurantLocations.IndexView({
restaurantLocations: this.restaurantLocations
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.show = function(id) {
var restaurant_location;
restaurant_location = this.restaurantLocations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.ShowView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
RestaurantLocationsRouter.prototype.edit = function(id) {
var restaurant_location;
restaurant_location = this.restaurantLocations.get(id);
this.view = new Lunchhub.Views.RestaurantLocations.EditView({
model: restaurant_location
});
return $("#restaurant_locations").html(this.view.render().el);
};
return RestaurantLocationsRouter;
})(Backbone.Router);
}).call(this);
Okay, this turned out to be a pretty esoteric problem. I had had a leftover
backbone-min.jssitting in myapp/assets/javascriptsdirectory, even though I had switched to using a different Backbone file. This “old”backbone-min.jswas getting loaded after my route definition and that’s what was messing things up. After I deletedbackbone-min.js, things started working.