DEV Community

RobL
RobL

Posted on

Bundled gems and not being that smart.

I've spent the past day looking at an issue with what appeared to be because of loosely defined dependencies. I thought perhaps the version of a gem that was being loaded was not the expected one and something very odd was going on, and hell the application I am working on is Ruby 2.6.5 so it might just behave slightly differently and someone fixed something that I've never seen before since then.

I am sure there was some command that could prune installed gems.

bundle pristine
Enter fullscreen mode Exit fullscreen mode

Nope that re-installs the bundled gems afresh. Ok, I can't remember but hell this will do it. This is where all the gems are located on this machine for this Ruby version.

rl@Robs-MacBook-Pro some_project % bundle show --paths
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actioncable-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionmailbox-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionmailer-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actiontext-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/actionview-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activejob-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activemodel-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activestorage-6.0.3.6
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6
...
Enter fullscreen mode Exit fullscreen mode

You Only Live Once.

rm -rf /Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/
Enter fullscreen mode Exit fullscreen mode

Ok that's screwed up a few things, I need bundler back to the version this project is bundled with and re-bundle everything

gem install bundler -v 2.3.26
bundle install
Enter fullscreen mode Exit fullscreen mode

Run the application and erm...application falls over because it can't find multi_json. This application does not have multi_json in it at all. It's not in the Gemfile.lock so nothing requires it at all. So why what?

I can follow the failure by sticking pry and capturing the backtrace.

It's falling over because json-schema requires it. How it's not a dependency of json-schema. If it were it would be in our Gemfile.lock

bundle show --paths | xargs grep -r multi_json
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/json-schema-3.0.0/lib/json-schema.rb:if Gem::Specification::find_all_by_name('multi_json').any?
/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/json-schema-3.0.0/lib/json-schema.rb:  require 'multi_json'
Enter fullscreen mode Exit fullscreen mode

spec/dummy/config/application/rb

# frozen_string_literal: true

require_relative "boot"

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "rswag"
# require "action_cable/engine"
# require "sprockets/railtie"
# require "rails/test_unit/railtie"

Enter fullscreen mode Exit fullscreen mode

It's when rswag is required.

begin
  require "rswag"
rescue => e
  binding.pry
  raise
end
Enter fullscreen mode Exit fullscreen mode

Ok, that tells me exactly where is required from.

This is it, it's in the json-schema gem and it is definitely requiring multi_json. And there must be an installed gem for it. So how come it's installed when it isn't?

if Gem::Specification::find_all_by_name('multi_json').any?
  require 'multi_json'

  # Force MultiJson to load an engine before we define the JSON constant here; otherwise,
  # it looks for things that are under the JSON namespace that aren't there (since we have defined it here)
  MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
end
Enter fullscreen mode Exit fullscreen mode

Ok, so I can be smart. But sometimes I am so smart I am stupid. There's the sucker. There is a specification for multi_json but there isn't a gem for it. Oh well. Serves me right for deleting stuff I shouldn't have.

/Users/rl/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/specifications/multi_json-1.15.0.gemspec
Enter fullscreen mode Exit fullscreen mode

Nuke the specification too and we're good. Hell I might just install multi_json and use oj for the speed.

Top comments (0)