backbone: Multiple backbones inside Node makes instanceof fail
This just consumed the last 4 hours of my life… and boy was it the most crazy difficult thing to debug.
If we have two modules:
- Module A provides custom backbone.js models
- Module B provides custom backbone.js collections
Then we have our app which:
- Requires Module A
- Requires Module B
- Creates a model instance using a custom model from Module A
- Creates a collection instance using a custom collection from Module B
- Adds the model instance to the collection instance
Then the sky falls down and burns all the horrible plagues at once. Why? I know the answer, but I’ll give you a gold star if you can guess it.
Here’s the answer: because our lovely model instanceof Model inside Backbone.Model.prototype._prepareModel fails, as the models are using one backbone.js and the collections are using another!!! Despite them being the same backbone.js version.
ARGH! That line needs to be better, perhaps check for the presence of a this.isBackboneModel variable defined by the Backbone.Model.prototype.
ARGHHHH. For now, it seems the only solution is to pass the Modules the Backbone.js module that we want them to use, rather than having them use their own local copies. Which is a real PIA. Which imho, the flag idea is a much better one.
Thoughts?
About this issue
- Original URL
- State: closed
- Created 12 years ago
- Comments: 17 (2 by maintainers)
Commits related to this issue
- Removed the harmful instanceof operator in preference for duck typing. Fixes #1288 — committed to balupton/backbone by balupton 12 years ago
I stumbled across this discussion while trying to figure out how instance testing gets handled with Node.js dependencies. I know I’m a bit late, but I think @balupton has been misunderstood.
Here’s the issue, stripped down:
thingv1.0.0 gets submitted to the npm registry. It exports aThingconstructor.thingutilsv1.0.0 gets submitted to the npm registry. It requiresthingv1.0.0, and has utility functions for creatingThinginstances.foobar, requiresthingv1.0.0 andthingutilsv1.0.0. I install them both vianpm, and therefore two separate package directories for the exact same version ofthing, version 1.0.0, get installed:foobar/node_modules/thingfoobar/node_modules/thingutils/node_modules/thingThinginstance in myfoobarapp usingthingutils.Thing, even though my app andthingutilsare both requiring the same exact version of thethingpackage, andthing.Thingis available to me. Node sees the twoThingconstructors (and their prototypes) as different because they come from “different” modules with different filesystem paths.I hope this helps someone else, as I was going a bit crazy trying to figure it out. This is the downside to the Node.js
node_modulessystem: while you avoid versioning hell in resolving dependencies, you can’t reliably test instances across modules the way you can in Python (where I come from) and other languages.You’re using package.json very incorrectly. A package.json should exist at the root of your application not your module. Each module having a package.json does not make sense, since the definitions therein define the package as an application. Therefore your entire application should have a single
node_modulesat the root containing a single instance of Backbone.js.There is nothing Backbone.js can do to solve this problem for you, its entirely a design decision to include two redundant copies of Backbone. There might be a way you can work around the issue, but instead you should try and figure out why you need multiple application configs (package.json) and eliminate those so you can avoid issues like this.