Janko
Janko

Reputation: 9335

Is it possible to require files outside the Gemfile?

For example, I'm developing a gem, and while I'm developing, I use pry instead of IRB, and debugger for debugging. However, I don't want possible contributors to have to install them (because they may not need them). My first idea was to put them in a Bundler group:

source :rubygems

gemspec

group :extras do
  gem "pry"
  gem "debugger"
end

And then people could use:

$ bundle install --without extras

But I want it to be a default that they're not installed. What would be perfect is that they're not in my Gemfile, but that I can still require them (if they exist on the computer). This solution would be ok because I don't care at which version they're locked. Can it be done?

Upvotes: 5

Views: 1105

Answers (4)

Jan M
Jan M

Reputation: 2225

Nowadays you can use the "optional" argument, and it will do exactly what you ask: it will not install the extras unless people bundle --with extras

group :extras, optional:true do
   ...
end

https://bundler.io/v2.3/guides/groups.html#optional-groups

Upvotes: 0

Jellicle
Jellicle

Reputation: 30286

You can add arbitrary load paths and then require gems from them. Check out the global variable $:

puts $:.inspect
# ["/var/myproject/releases/20200918191637/lib", "/var/myproject/releases/20200918191637/vendor", "/var/myproject/releases/20200918191637/app/assets", "/var/myproject/releases/20200918191637/app/controllers", "/var/myproject/releases/20200918191637/app/helpers", "/var/myproject/releases/20200918191637/app/mailers", "/var/myproject/releases/20200918191637/app/models", "/home/deploy/.rvm/gems/ruby-2.3.0/gems/bundler-2.0.2/lib", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/gems/2.3.0/gems/json-1.8.3/lib", "/home/deploy/.rvm/gems/ruby-2.3.0/gems/bundler-2.0.2/lib/gems/bundler-2.0.2/lib", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/x86_64-linux", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby/2.3.0/x86_64-linux", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-linux"]

Now let's append to $: and require a gem

require 'method_source'
# LoadError: cannot load such file -- method_source
$: << '/home/deploy/.rvm/gems/ruby-2.2.4@myset/gems/method_source-1.0.0/lib'
# ["/var/myproject/releases/20200918191637/lib", "/var/myproject/releases/20200918191637/vendor", "/var/myproject/releases/20200918191637/app/assets", "/var/myproject/releases/20200918191637/app/controllers", "/var/myproject/releases/20200918191637/app/helpers", "/var/myproject/releases/20200918191637/app/mailers", "/var/myproject/releases/20200918191637/app/models", "/home/deploy/.rvm/gems/ruby-2.3.0/gems/bundler-2.0.2/lib", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/gems/2.3.0/gems/json-1.8.3/lib", "/home/deploy/.rvm/gems/ruby-2.3.0/gems/bundler-2.0.2/lib/gems/bundler-2.0.2/lib", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/x86_64-linux", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby/2.3.0/x86_64-linux", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/vendor_ruby", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0", "/usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-linux", "/home/deploy/.rvm/gems/ruby-2.2.4@myset/gems/method_source-1.0.0/lib"]
require 'method_source'
# true

That can be tedious if you have a lot of dependencies, though, so you might try this:

Dir['/home/deploy/.rvm/gems/ruby-2.2.4@myset/gems/*'].each do |gem_path|
  $: << File.join(gem_path, 'lib')
end

Upvotes: 2

severin
severin

Reputation: 10268

You could add a conditional based on environment variables into the Gemfile. Example:

source :rubygems

gemspec

if ENV['WITH_EXTRAS'] == '1'
  gem "pry"
  gem "debugger"
end

The gems are then only installed/loaded, if you set the environment variable to '1' e.g. WITH_EXTRAS=1 bundle install.

Upvotes: 0

pje
pje

Reputation: 22757

bundle install is "opt-out"—unless you specify --without some_group, it installs everything.

If you absolutely don't want to have a given gem in your Gemfile, you could just gem install that rogue gem outside of your bundle. Then it'll be visible to you under irb and straight ruby (but obviously you'll get errors if you try to require it within code running under bundle exec).

Upvotes: 0

Related Questions