DEV Community

RobL
RobL

Posted on

1

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.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs