Fighting Against Gem Hell

There is a term called DLL Hell which in my opinion exists also in the Ruby community with the different name - Gem Hell. This potential problem exists when dependencies for your project and/or libraries are not managed properly.

I’ve written in the post WatirSplash 2 about loading all the dependencies with the help of the Bundler, which helps to organize the dependencies in a sanely way and tries to eliminate the Gem Hell problem. In this post i’m gonna give a more detailed overview of how the things were before and how they are now in the WatirSplash framework.

Story Behind WatirSplash’ Dependencies

Since WatirSplash is a framework which supports using different frameworks for browser automation (Watir, Watir-WebDriver and FireWatir) then there needs to be some kind of a mechanism for defining the install and runtime dependencies. Install dependencies are easy to specify since they can be put right into the .gemspec file of the WatirSplash gem and RubyGems does all the heavylifting:

It gets trickier when it comes to specifying the runtime dependencies. “Why runtime dependencies at all?” - you might ask. The answer to this question is fairly simple - because the framework used for automating the browser is chosen during runtime and it’s not possible to put all these gems into installation dependencies due to the problem of Watir (for controlling the IE browser) not installing successfully on Linux or OS X operating systems for obvious reasons. There are also other OS-specific gems. Also, it’s not possible (at least not in my knowledge of) to specify platform specific dependencies right into the .gemspec file itself.

The Old Way

The runtime dependencies in WatirSplash 1 were loaded with the help of the RubyGems itself. When the desired framework was specified then WatirSplash loaded the appropriate file, which executed the code similar to this for Watir:

It meant that the user of WatirSplash needed to have the Watir version 2.0.1 installed and if he didn’t then the installation instructions were provided.

This solution seems to solve the problem of specifying runtime dependencies at first. There are still some problems with this approach. First of all, if Watir has a dependency for some other gem without any specific or with too loose version then it is possible that some newer version of that gem breaks the usage of WatirSplash and i, as a maintainer of the WatirSplash gem, have to release a new version of the WatirSplash gem by specifying the exact version of that gem as a runtime dependency. Second problem is that if a newer version of Watir (or any other among the runtime dependency gems) were released then it was not possible for the user of WatirSplash to try if it was working with the current version of WatirSplash (which was pretty often the case) without modifying the code of WatirSplash itself or waiting for the new release made by me with updated runtime dependencies. These are the two main and quite big problems with this approach.

The New Way

These problems were solved by introducing the usage of Bundler. Bundler allows to specify runtime dependencies exactly like with RubyGems, but it has a difference of locking down the dependencies versions. This means that user A and user B are always using the same versions of all the runtime dependencies no matter what other versions they have installed on their system.

By using WatirSplash 2, you will get the following Gemfile into your specs directory, when running new project generator, for specifying all the needed dependencies:

After executing `bundle install` do not forget to add Gemfile.lock also into your VCS - this is the only way to guarantee that everyone who is running the tests are using the exact same versions of the dependencies.

This solution allows each user of the WatirSplash to specify their own dependency versions without any need to wait for the new release of the WatirSplash itself. In other words - this solution solves both of the problems existent in the previous RubyGems solution.

Conclusion

Bundler tries to make the Gem Hell problem disappear and is doing a pretty good job there, but if there are gems which depend on some external native library, which needs compilation then there is still the danger of having a wrong version of that dependency causing compilation errors. Probability of seeing that problem is quite low compared to the problems which Bundler solves. All in all Bundler is a really great tool and thanks to that WatirSplash has gotten even better.