How can I install a gem as if it was specified in a Gemfile? - ruby

I want to install a gem via gem install, but I need it to resolve with dependencies of the current project.
Basically I want the functionality that bundler gives me when I specify gem 'xyz' in a Gemfile, but I don't want to add that specific gem into the Gemfile.
I tried doing bundle exec gem install ... but it doesn't seem to work.
edit: The reason why I don't want to add it to the Gemfile is that it might be something like metric_fu, metrical, saikuro, rails_best_practices, etc. Simply gems that are kind of utility use and might only cluttler the project.
I might only want to use them temporarily, or install them, try out, if it doesn't work out the way I want do rvm gemset empty and bundle install again to clean up.

The point of Bundler is, in part, to prevent you from doing things like that (to prevent you from injecting gems from outside when your project doesn't declare them).
Looking for a way of doing that is looking for a bug in Bundler. If you did manage to find some way of skirting Bundler's enforcement mechanisms, you should probably not use it; instead, you may consider filing it as a bug with Bundler's issue tracker.
Now we come to the real questions: what can you do? and what should you do?
You should use either RVM gemsets or Bundler to isolate your application and its gem dependencies. You don't need both. I would recommend Bundler for this purpose over RVM gemsets.
You should add to your Gemfile any gems that you want to use and that integrate with your application (i.e., that either load your application or that are loaded as part of your application). This is not a requirement for any gems that refrain from integrating with your application.
You should refrain from committing a changed Gemfile or Gemfile.lock to version control until you are satisfied that your application continues to operate acceptably (tests pass, new gem does something useful, etc.).
Or you should stop using Bundler, because you want to do things it is explicitly designed to prevent you from doing (not recommended).

At the risk of sounding dumb, why not add it to the gemfile? You can always add it to its own group if you don't want to have to install it everywhere.

A slightly different approach is, if you're using version control, such as Git, to create a new branch and install the gems. If it doesn't work out, uninstall the gem (I'm not sure this will be done by bundle update on the old branch) and trash the branch. If it does, work, merge your stuff into the old the branch.
Though I do believe the other answers and comments have some very good points.

Related

RubyGems plugin to tame a big ball of already-installed gems?

Maybe someone knows if this sort of RubyGems plugin exists already, before I try to sink a lot of time into writing one myself.
I'm not using RVM* or Bundler (edit: see thread in comments), so I have a big ball of system gems installed. I want to sort out which ones are gems I really want to use, which ones are dependencies that have to be there for the gems I really want to use, and which ones are just junk that can be cleaned up.
If anyone is familiar with Gentoo, I'm thinking of something similar to Gentoo's package management, but for RubyGems instead--a way to tag a small list of gems I really want to keep, then run a command that can go through all of my gems and clean up the ones that aren't dependencies of those gems. A "#world" set for RubyGems, in other words.
*RVM isn't an option for me anyway, because I have to use Microsoft Windows.
If you install graphviz, then you can runbundle viz this will produce a dot notation mapping of the dependencies and you can use that to trace dependencies down to those gem's you actually need to have installed (but only those that you have installed via bundler).
bundle viz --format=dot

Why should I use application-specific RVM gemsets in addition to Bundler?

I'm using RVM to manage my local Ruby installations, and Bundler for application dependency management.
Some people recommend using a separate RVM gemset for each application, while some seem to think that's not necessary.
So what are the advantages of using a separate RVM gemset for each application, when I'm using Bundler anyway? What are the risks of not doing so?
i use gemsets in addition to bundler because of the following:
easy to just drop everything once a while (i like messing around with my installed gems)
no need to call bundle exec (this is obsolete with binstubs)
faster loading, because less gem-specs need to be parsed
easy to distribute (copy it to your mates)
there are probably more reasons to use them, but i generally like the idea of sandboxes!
I've found that it's useful to have rvm if you're using rails 2. RVM is great if you need to work on an app that has old code. Rails 2 doesn't use a Gemfile, so bundle exec doesn't work. RVM makes it easy to keep the gem versions correct for that project, and they you can switch back to newer versions of rails and use the Gemfile to specify versions. If you have multiple apps that use different gem versions, but the same version of ruby, it's convenient to share most of the gems, and specify them in the Gemfile where they differ.
I think it's kind of case dependent. If you find that there are tons of version issues between two apps, and constantly modifying Gemfiles to keep them straight is annoying, then use separate gemsets. If there is enough in common, it might make sense to just use the same gemset
RVM gemsets allow you to separate gems without loading bundler - which is faster, it will be simpler to load the gems.
You should be using gemsets to just separate projects from your helper gems (like gist).
But if you decide that gemsets are of no help for you you can tell RVM to ignore gemsets totally:
echo "export rvm_ignore_gemsets_flag=1" >> ~/.rvmrc
Might I also refer you to the 'globalcache' documentation in the form of an rvm-test located at fast/globalcache_comment_test.sh in conjunction with your projects' Gemfile.
This will also cut down on the network traffic to rubygems.org. Initial loadout of global, not withstanding.

Why does RVM install duplicate gems for different gemsets?

So, I've created a separate rvm gemset for each of my rails projects. They both use the same version of ruby 1.9.3.
This causes bundle install to completely install a fresh set of gems for both projects. It doesn't matter if the other project has the exact same version of the gem installed in the other gemset. I'm guessing this is the expected behavior to me but it seems like an inefficient use of hard drive space and bandwidth.
I know that I could manually move some of those gems to a global gemset, but that seems tedious to me and also prone to breaking if my dependencies change for a particular project.
Is there a better way to organize things, or have rvm auto detect when a gem version is already installed and just use that copy?
Or is there a better alternative to RVM that I should be using.
This is by design. Gemsets allow you to completely isolate the libraries used so you don't have any accidental interaction between projects. If you don't need the isolate you can just use an interpreter without a gemset:
rvm use 1.9.3
If there are a few gems you use across all projects, just switch to the global gemset for the interpreter:
rvm use 1.9.3#global
gem install the common gems and then they won't be re-installed per-project anymore when you are in a gemset.
While gemsets definitely aren't efficient in terms of bandwidth or HD space, they are extremely handy because you can easily blow away all dependencies for a project and re-bundle from scratch any time you want to. They also completely eliminate accidentally changing versions of your dependencies. If you don't like gemsets, correctly specifying versions in your Gemfile can get you pretty far on this without them.
As far as alternatives, rbenv is the main one I'd check out.

How to make a gem available that isn't listed in Gemfile

I made a gem for myself to use in the console. I want to be able to use it all the time everywhere.
I can't figure out how to get Bundler to recognize it without putting it into my Gemfile, but that requires the rest of the people on my team to know about it and have it installed.
Is there a way to get Bundler to overlay a Gemfile of my choosing? Or to somehow generally make my gem available to me even though it is not listed in my Gemfile?
You could circumvent bundler by putting this at the end of the Gemfile and gitignore the Gemfile.dev.rb:
dev_gemfile = File.expand_path("Gemfile.dev.rb", File.dirname(__FILE__))
instance_eval(File.read(dev_gemfile)) if File.exists?(dev_gemfile)
Your Gemfile.lock will not match on different developers' machines if their Gemfile.dev.rb didn't match but I'm only concerned with exact matches in production. Minor changes between developers and production are already an issue if you have multiple platforms and can be worked around in the same way.

Ruby: just-in-time gem installation?

Would it be possible to override the default "require" by adding automatic download-and-install code for any missing includes (provided that the missing include is published as a ruby gem).
Which would not work in situations where Ruby is not interfaced with a shell. But still I think it would be an interesting idea.
Is there such a mechanism in existence today?
Edit:Removed portion about password check. I just checked and gem install doesn't seem to require me to type my password.
You would be able to hijack require method so as gems are installed when an attempt is made to require them, but still you won't have access to newly installed gem in current process, because gem index has to be reloaded.
I understand the intentions but I think exercise might not be worth it.
When installing a fresh gem the gem will be installed in the GEM_HOME. If that is not writable then it will try in the user's home .gem directory (on *NIX at least).
You could certainly script this. In a way Rail's rake gems:build is just this. Just not on demand.
But, I would recommend against this. You could run into build, versioning, dependency and network issues. And probably security issues as well.
PS: Francis Hwang did something related a while ago, although only as a require, not a require gems.
http://fhwang.net/2005/11/01/urirequire-I-got-yer-Web-2-0-right-here
A better option would be to use bundler and distribute the required gems with the application.
It is also quite simple to write a script to bootstrap the installation of gems if you didn't
want to distribute them with your code (using the bundle install/check commands)

Resources