DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

Open Source Adventures: Episode 37: Fixing beeminder gem to work with Ruby 3

Here's an easy thing I needed to do. I was setting up a new laptop, with latest version of Ruby, and the script I used to snapshot beeminder data stopped working.

It turns out to be a trivial issue. beeminder gem depends on json 1.x, which doesn't work with Ruby 3. Simply changing that to json 2.x fixes it.

It also turns out this was already fixed, years ago, but the fix was never released. So all I did was poke them on GitHub issues.

Hotfixing gem dependencies

This is fine, but I have no patience for waiting for a new release.

So here's a hacky thing I did.

I installed latest version of json with gem install json.

Then I checked where beeminder gem is installed:

$ EDITOR=echo gem open beeminder
Enter fullscreen mode Exit fullscreen mode

So my first idea was to hotfix /Users/taw/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/beeminder-0.2.12/beeminder.gemspec by replacing:

  gem.add_dependency 'json', '~> 1'
Enter fullscreen mode Exit fullscreen mode


  gem.add_dependency 'json', '~> 2'
Enter fullscreen mode Exit fullscreen mode

That however did not work, as Rubygems is caching dependency information.

I needed to change /Users/taw/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/specifications/beeminder-0.2.12.gemspec. Here's the final file:

# -*- encoding: utf-8 -*-
# stub: beeminder 0.2.12 ruby lib do |s| = "beeminder".freeze
  s.version = "0.2.12"

  s.required_rubygems_version =">= 0".freeze) if s.respond_to? :required_rubygems_version=
  s.require_paths = ["lib".freeze]
  s.authors = ["muflax".freeze, "bsoule".freeze] = "2018-09-27"
  s.description = "Convenient access to Beeminder's API.".freeze = ["".freeze]
  s.executables = ["beemind".freeze]
  s.files = ["bin/beemind".freeze]
  s.homepage = "".freeze
  s.rubygems_version = "3.3.7".freeze
  s.summary = "access Beeminder API".freeze

  s.installed_by_version = "3.3.7" if s.respond_to? :installed_by_version

  if s.respond_to? :specification_version then
    s.specification_version = 4

  if s.respond_to? :add_runtime_dependency then
    s.add_runtime_dependency(%q<activesupport>.freeze, [">= 3.2", "< 6"])
    s.add_runtime_dependency(%q<chronic>.freeze, ["~> 0.7"])
    s.add_runtime_dependency(%q<json>.freeze, ["~> 2"])
    s.add_runtime_dependency(%q<highline>.freeze, ["~> 1.6"])
    s.add_runtime_dependency(%q<optimist>.freeze, ["~> 3"])
    s.add_runtime_dependency(%q<tzinfo>.freeze, ["~> 1.2"])
    s.add_dependency(%q<activesupport>.freeze, [">= 3.2", "< 6"])
    s.add_dependency(%q<chronic>.freeze, ["~> 0.7"])
    s.add_dependency(%q<json>.freeze, ["~> 2"])
    s.add_dependency(%q<highline>.freeze, ["~> 1.6"])
    s.add_dependency(%q<optimist>.freeze, ["~> 3"])
    s.add_dependency(%q<tzinfo>.freeze, ["~> 1.2"])
Enter fullscreen mode Exit fullscreen mode

And that worked.

Should you do this?

To be honest, I don't really recommend doing this. Hotfixing globally installed dependencies is generally a poor idea, and there are more proper ways to do this.

You can also use this kind of hotfixing to quickly check if you're on a right track. If the gem was crashing with updated json, I'd know it's something bigger.

If you do so, you should uninstall and reinstall that gem afterwards to make sure no edits remain.

Coming next

For the next episode I'll go back to the Russian losses tracker, as there's a few more things I want to add.

Top comments (2)

bsoule profile image

I released a new version of the Beeminder gem. Let me know if it fixes the Ruby 3 support issue!

taw profile image
Tomasz Wegrzanowski

It works now, thanks.