Saturday 27 October 2012

[SOLVED] undefined method `name' for "Ascii85":String

So, we're still using Rails 2.3.2 for our client... but I'm *trying* to upgrade it piece by piece. In doing so, I recently had to upgrade rubygems, so that it would work with a recent version of a gem we desperately needed.

Unfortunately it led to the undefined method `name' for "Ascii85":String bug that I wrote about when I last tried to upgrade rubygems

Back when it broke rubygems the first time, the only solution seemed to be to downgrade rubygems and hope for a future time when I could upgrade everything and get it working again.

But that wasn't an option this time... and so I had to hack up a solution.

The problem is described below in solution 2, but it's basically a problem with rails - which isn't using the newer rubygems gem-comparing "==" function properly any more.

Solution 1: Gem bundler

One solution that definitely works is to upgrade to using gem bundler (or the Rails2.3 version of bundler).

This definitely works because bundler doesn't have the same bug in it that Rails 2 has - it uses gem-comparison the new way.

But some of our clients aren't on the bundled release yet, and I need to quickly fix bugs and push to those clients... so I needed a solution that would let me still load the bundler-free version without having to downgrade rubygems to do it.

Solution 2: Fix rails

This solution requires a (very small) hack on Rails... but I figured that was ok as it was just to get my own system working so I can fix things without having to go through the pain of installing rvm (which I don't have time for right now).

So far the fix seems to be working, so I'll share (with the caveat that it's not well tested yet so YMMV).

The problem is really a Rails bug... not rubygems. So that's where you can safely hack (for now). From the stacktrace of the bug, find the copy of "rails/gem_dependency.rb" that is causing the issue:

/usr/lib/ruby/gems/1.8/gems/rails-2.3.2/lib/rails/gem_dependency.rb:239:in `==': 
undefined method `name' for "Ascii85":String (NoMethodError)
 from /usr/local/lib/site_ruby/1.8/rubygems/dependency.rb:218:in `==='

In my case, I opened /usr/lib/ruby/gems/1.8/gems/rails-2.3.2/lib/rails/gem_dependency.rb in a text editor (with sudo permissions). It'll have something like the following:

    def ==(other)
      self.name == other.name && self.requirement == other.requirement
    end

The actual problem occurs because Rails is sometimes passing the name already as a string to this function, instead of an actual spec. So to fix it, we just check for that with the following code:

    def ==(other)
      # The following line has been inserted to get around the bug:
      # "undefined method `name' for "Ascii85":String (NoMethodError)"
      return self.name == other if other.is_a?(String) # bugfix
      self.name == other.name && self.requirement == other.requirement
    end

It shouldn't alter existing functionality, it'll just get past the broken code that is in rails until you can upgrade rails, or use bundler.

If you (horror) actually need to install this fix on a live system; I'd recommend freezing rails to your gems directory before applying the fix. But in reality, I'd actually recommend just finding a way to upgrade to using bundler. It's a neater solution that won't require ongoing maintenance.

No comments: