Leahcim
Leahcim

Reputation: 41919

underscore backwards compatibility

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

Upvotes: 0

Views: 753

Answers (1)

machineghost
machineghost

Reputation: 35750

You can run two versions of Underscore simultaneously. Simply load your version of Underscore on the page first, then add this line:

var underscore = _.noConflict();

to alias your version of Underscore to the underscore variable (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 = a you can also do var b = _; and then you could do b.map() or whatever. Well, almost; because Underscore keeps an internal reference to Underscore, you need to update it, which is where noConflict comes 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 _ with alert just 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 _ to underscore (or anything else), your Rails app can keep referencing version #2 as _, and your code can keep using version #1 as underscore.

Upvotes: 1

Related Questions