For my master thesis, I was working on a low-level project where I have to develop a few gems that are not only dependent on one another, but would have to be developed in parallel. One of the main problems I faced was adding the dependency in a proper way that would be clean (not hackish) and DRY.
The problem arose when I wanted to make a gem dependency hierarchy that looked something like omniauth
- I would have a base gem that would not be of much use on its own which I will call parent gems (like the actual omniauth gem, which is never used alone), and
- I would have a few gems that would somehow depend on my base gem which I will call child gem (collectively children gems) (like the strategies provided for omniauth, e.g. omniauth-github.)
The vision was that for future projects to only include a single child gem (like omniauth-github) and all features and definitions in the the parent gem be accessible to the rails project, as well (e.g. monkey patches, etc.)
Update With time, I realized devgem has become an incredibly clean way to develop gems even if they are standalone. In another case, I am developing an interactive console-based gem and using devgem for development makes development/debugging/testing so much easier.
The Silly Solution
The tiresome silly solution
The tiresome way would be to install my parent gem AND my child gem every time I make a change to them. This way I would simply use the child-gem from my Gemfile and simply require my parent-gem from my child-gem (makes sense)
As as I said, this makes sense and should be the way to go, except bundling every time is not a very time-friendly way to go.
The dumb silly solution
The silly solution consisted of two parts. First, the gems in my project would require a path option to tell bundler where to load my gems from. The second, more serious problem, was that I had to explicitly add my parent gem to the Gemfile for my project to be able to use the functionality provided there.
gem 'parent-gem', path: '/path/to/parent/gem'
gem 'child-gem-1', path: '/path/to/child/gem1'
This would save me the hassle of having to `rake install` my gem file after every step, and instead keep my gem loaded from my development directory.
The Proper Solution – Devgem
Proposed by Florian, the idea is simple: after installing your gem locally, symlink to it. Genius! So the typical usage scenario becomes:
- Create gem
- Bundle it and install it
- Remove the source found in $GEM_HOME/gems/child-gem-0.0.1
- Create a symlink to your development source instead
And here’s where devgem comes into play: it performs just that for you (needless to say, devgem is a few lines of code.) You can check the source, installation steps, and usage on Github.
Alternatively, you could run a gems server that would handle your updates locally, but that would require adding an extra layer above your project development process. Make your pick.