Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails optional gem config

What do you do when you want to use a gem for development/testing that you don't want to force other devs to use? Right now I have

begin
  require 'redgreen'
rescue LoadError
end

in test_helper.rb and no gem config, but that seems like a clumsy approach, albeit a functional one. I'd like to do something like the following:

config.gem "redgreen", :optional => true

Any other suggestions? Or should I just vendor those pretty superficial gems...?

EDIT

To be clear, I am only talking about those specific gems, like redgreen, which aren't actually used in the functional code, but only in the coding process. There is no need to vendor these at all, except to avoid the conditional require.

like image 725
tfwright Avatar asked Jan 22 '10 18:01

tfwright


People also ask

How do I specify a gem version?

There are several ways to specify gem versions: Use a specific version: gem "name-of-gem", "1.0" . You can find specific versions on Rubygems.org (provided that's the source you”re using) by searching for your gem and looking at the “Versions” listed. Use a version operator: gem "name-of-gem", ">1.0" .

What is Gemfile for?

A Gemfile is a file that is created to describe the gem dependencies required to run a Ruby program. A Gemfile should always be placed in the root of the project directory.

Where do I put Gemfile?

A Gemfile describes the gem dependencies required to execute associated Ruby code. Place the Gemfile in the root of the directory containing the associated code. For instance, in a Rails application, place the Gemfile in the same directory as the Rakefile .


3 Answers

Gems that are specific to your development environment should be installed in your gemset or local gems, but not in the Gemfile.

A classic example is the ruby-debug-base19x which Rubymine needs for debugging. This is installed in your local gemset, but not in the Gemfile because not all coders use Rubymine.

[EDIT]

Indeed, everything is run in the context of the bundle, and outside gems are not reachable. There do exist some workarounds indeed. Most of them are dirty :)

I found a lot of good solutions in this bundler issue.

The nicest solution was to add this to your .irbrc :

# Add all gems in the global gemset to the $LOAD_PATH so they can be used even
# in places like 'rails console'. 
if defined?(::Bundler)   
  global_gemset = ENV['GEM_PATH'].split(':').grep(/ruby.*@global/).first 
  if global_gemset
    all_global_gem_paths = Dir.glob("#{global_gemset}/gems/*")
    all_global_gem_paths.each do |p|
      gem_path = "#{p}/lib"
      $LOAD_PATH << gem_path
    end   
  end 
end

require 'irb/completion' 
require 'rubygems' 
require 'wirble'

Wirble.init 
Wirble.colorize

If you then install wirble to the global gemset, it can then be found. Original source: https://gist.github.com/794915

Hope this helps.

like image 65
nathanvda Avatar answered Sep 28 '22 11:09

nathanvda


I answered a similar question of my own here

User-level bundler Gemfile

One way to do this is to create different environments:

group :scott do 
end

Then

bundle --with-env=scott
like image 38
Scott Schulthess Avatar answered Sep 28 '22 13:09

Scott Schulthess


Ok, I think I've come up with something. Basically, the idea is to only execute a secondary Gemfile when a Rails app is executing. To do this we add two things:

First, we alter the rails script a little:

# in ./script/rails

Kernel::IN_RAILS_APP = true

APP_PATH = File.expand_path('../../config/application',  __FILE__)
require File.expand_path('../../config/boot',  __FILE__)
require 'rails/commands'

Second, we tell bundler to pull in the secondary Gemfile if we're in a rails app and a secondary file exists:

# Gemfile

if Kernel.const_defined?(:IN_RAILS_APP)
  local_gemfile = File.dirname(__FILE__) + "/Gemfile.local"
  if File.exists?(local_gemfile)
    puts 'using local gemfile'
    self.instance_eval(Bundler.read_file(local_gemfile))
  end
end

Now you can add a Gemfile.local to your project and run specific gems on a per-machine basis. bundle install works normally since the IN_RAILS_APP constant doesn't exist.

** Make sure to add Gemfile.local to your .gitignore.

like image 26
mnelson Avatar answered Sep 28 '22 12:09

mnelson