Léonard Henriquez
Léonard Henriquez

Reputation: 738

Use a gem locally in a rails app without modifying the Gemfile

I need to locally use a gem (Rails Panel) in a rails app without adding code to git.

The reason I cannot modify code in version control is because my team has a very strict policy on adding new gems. It's not ideal but I can exclude files from version control if I have to.

I tried the following solution but it doesn't work:

  1. Run gem install meta_request

  2. Modify the file bin/rails with the following code:

#!/usr/bin/env ruby

# original code [...]

gems = %w[meta_request]
gem_home = ENV['GEM_HOME']
gem_dir = Dir["#{gem_home}/gems/*/lib"]
gems.each do |gem|
  gem_path = gem_dir.select { |r| r.include?(gem) }
  $LOAD_PATH.append(*gem_path)
  require gem
end
  1. Add bin/rails to .git/info/exclude

NB: The answer to this thread doesn't work in this case because the gem needs to be "required". How can I use a gem locally without forcing it on collaborators?

Upvotes: 5

Views: 1069

Answers (3)

Abubakar Azeem
Abubakar Azeem

Reputation: 324

Solution 1 (easy to understand but not generic)

A quick solution without modifying the load path.

Step 1, open a terminal and run this command to get full path of the gem that you want to use locally:

gem which GEM_NAME

Step 2, create an initializer file local_dependencies.rb in config/initializers/ and require your gem(s) in the file like this:

# file: config/initializers/local_dependencies.rb

require 'GEM_FULL_PATH'

Step 3, edit .git/info/exclude and exclude local_dependencies.rb file:

# file: .git/info/exclude

config/initializers/local_dependencies.rb

All done!

Solution 2

This is a more generic solution, although both solutions are bypassing bundler but the advantage is that you don't have to update the Gemfile.

Create an initializer file local_dependencies.rb in config/initializers/ and add this code:

gems = {
  'meta_request' => '0.7.2',
}
gem_home = ENV['GEM_HOME']
gems.each do |gem_name, version|
  gem_path = "#{gem_home}/gems/#{gem_name}-#{version}/lib"

  raise "GemNotFound: name: #{gem_name}, version: #{version}" unless File.directory?(gem_path)

  $LOAD_PATH << gem_path
  require gem_name
end

Edit .git/info/exclude and exclude local_dependencies.rb file:

# file: .git/info/exclude

config/initializers/local_dependencies.rb

All done!

Upvotes: 3

Les Nightingill
Les Nightingill

Reputation: 6156

There's nothing magic about the environment names, ('development', 'production', 'test'). So you can define an environment that you alone use, like 'lh_development'.

To support this you will need a file config/environments/lh_development.rb, which would essentially be a duplicate of config/environments/development.rb. And in your Gemfile, you can define the gems included in the :lh_development group...

group :lh_development do
  # here list all the same gems that are included in the :development group
  gem 'meta-request'
end

then you will start your server on your dev machine with

RAILS_ENV=lh_development rails s

of course, you would be ill-advised to test your code with your special gem included, b/c your test build should be the same as the other devs and the production build.

I suppose this does not strictly meet your requirement to not modify Gemfile, but it does so in a way that doesn't affect other devs or test/production env. So maybe your team can live with it?

Upvotes: 0

Rishabh Aggarwal
Rishabh Aggarwal

Reputation: 1

You can always define groups like development or test which won't effect anything in production so you can push them to git without worrying about the code.

group :development do 
   gem 'gem-name'
end

or

group :test do
   gem 'gem-name'
end

Upvotes: 0

Related Questions