I’m trying to play around with a backbone app that was made with an older version of underscore (1.2.0) inside a newer rails app that has a more recent version of underscore loaded (the underscore that comes with the current version of backbone-on-rails gem), so this is a backwards compatibility issue, which I can’t figure out even with the help of the changelog http://underscorejs.org/#changelog, however, it’s happening when I’m trying to save data.
Context:
A Company, created by the Companies collection, is trying to save (with the setBucket function) the id of the Bucket it is contained in (see code below).
This is the error I get when I try to save data.
Error
<error>
_.extend
_.clone
_.extend.toJSON
_.extend.save
_.extend.update
Backbone.sync
_.extend.sync
_.extend.save
window.Company.Backbone.Model.extend.setBucket
window.AppView.Backbone.View.extend.createCompanyOnEnter
jQuery.event.dispatch
elemData.handle.eventHandle
Source Code
…(code ommitted)…
var company = Companies.create({text: text}); #this works. company is created
company.setBucket(initialBucket.id); #this triggers the error
….(code ommitted)
setBucket: function(bucketId) {
this.save({bucket: bucketId}, {silent: true}); #the function that's not working
You can run two versions of Underscore simultaneously. Simply load your version of Underscore on the page first, then add this line:
to alias your version of Underscore to the
underscorevariable (you can of course use a different alias if you prefer). Then run a find/replace on all of your existing Underscore-using code to replace “_” with “underscore” (or your alias).Finally, load your Rails app and it version of Underscore to the page. It will get the
_alias, and your code can use its version without impacting your library’s version.* EDIT *
Ok, here’s a little more background. In Javascript (just as in Ruby I believe) functions are first-class objects. This means that
_isn’t technically the Underscore function itself, it’s just a variable that points to the “true” Underscore function (which is itself an object). This also means that you can make aliases to functions the same way you do with any other variable. Just as you can do:var a = 5; var b = ayou can also dovar b = _;and then you could dob.map()or whatever. Well, almost; because Underscore keeps an internal reference to Underscore, you need to update it, which is wherenoConflictcomes in; that code really should have been:var b = _.noConflict();By the way, it also means you can go the other direction and change
_, if you want:_ = alert; _('hello world').So, what’s currently happening with you is that you bring in Underscore on to your page. Presumably you’re doing this by putting an
<script src='underscore.js'></script>in your main html.erb file. This brings in Underscore version #1. Then you load your Rails app; I’m not sure exactly how this is working, as it depends on your app, but somehow that app is putting another script tag on the page, pointing to Underscore version #2.This is a problem, because Underscore version #2 just replaced your version #1 (the same way I replaced
_withalertjust now). This breaks your code. You could fix it by just adding your<script>tag after the one from your Rails app. This would restore version #1 and fix your code … but break your app’s code.What you really want is for your code to use version #1 and your app’s code to use version #2. Which is where my original answer comes in: by re-aliasing version #1 of
_tounderscore(or anything else), your Rails app can keep referencing version #2 as_, and your code can keep using version #1 asunderscore.