Referencing multiple local ruby gems in development using Bundler - ruby

I currently work on an application that consists of many gems. Each of these gems are being developed at the same time, and it is important for us to reference our current local copy from each of the gems.
We currently use Bundler in each of these gems. Currently we are setting an environment variable that tells Bundler to reference our local copies as opposed to the system installed gem.
While this works, it is messy because:
1) The Gemfile.lock is constantly changing when we flip back and forth. This results in errors when deploying.
2) This relies on all developers keeping their directory structures exactly same, unless we also make this configurable (sucky).
What do other people do in this situation?

Upload your gems to private repositores in github, for example, and let Bundler feed from them. Your gem developers should have their repos updated.

Related

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.

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

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.

Getting newer gems

I'm really just a beginner to ruby, so hopefully this is an easy one. I've got to the point where I'm starting to look into some of the gems that the community have put together. I decided to check out something that would help my application consume rss feeds. So, headed over to rubygems (which is where i thought people go to get these kinds of things) and searched for rss. I found this one;
http://rubygems.org/gems/simple-rss
instructions were to just install the gem with
gem install simple-rss
So far, so good. When i came to actually use the gem, the documentation I received from doing the above was a bit naff, so i searched a bit further and found the git repo;
https://github.com/cardmagic/simple-rss
The documentation there (their code examples) complain about missing methods etc. and after a bit of digging I came to the conclusion that I must have downloaded an older version of the gem than the git trunk.
So, my question is, should I be using rubygems to get the latest gems, and if not, what other resources are out there to help find the latest builds of the comminities gems?
As far as finding a good gem for a task — use Ruby Toolbox, since it also shows you how actively maintained a gem is. Here's, for example, a section on feed parsing.
If you want to get the latest gem code that hasn't been released yet, you could download the code directly from github and build the gem yourself. However, it's easier to use bundler for that. It allows you to create a Gemfile for your project looking something like the following.
gem 'simple_rss', :git => "git://github.com/cardmagic/simple-rss.git"
Then run bundle command to download and build these gems from their corresponding sources.
In general, bundler is a great solution for managing gem dependencies for any ruby project. It provides ways to quickly reference any released gems, automatically builds gems directly from a git source, git refs, or paths on your filesystem, and has other convenient features.
By far the best place for all things Ruby & Ruby on Rails for the devs is the Ruby Toolbox

nested rails gems and gem management

Rails is collection of several gems, all who's source resides in the rails repository, aka active_record has its own gemspec but is at github.com/rails/rails/active_record. While I use this stuff all the time, I dont really know the details of creating my own gems using this strategy. I have a project for work where certain codebases will be reused from project to project, and think that I would like to build gems for each recurring toolset. While the gems will always be used in a namespace, eg Company::LegacyRecord I think it would be ideal to have LegacyRecord, in this case be its own gem. What would be the rationale for building a collection of gems with a toplevel namespace, like Company, in my example, or rails as the top level namespace, versus gems that are totally independent?
you probably only need to do that for very large projects. The benefit is that you can "split up the functionality" across gems and each one is more specialized.

Resources