2

I'm working on writing a gem that has several gem dependencies, one of which depends on a gem that broke backwards compatibility in a newer version. This got me to thinking - I don't want the gem that I'm building to become "that gem" that is making it difficult for people to update their application. I also don't want to force people using my gem to have to use specific versions of the gems it depends on in the rest of their application.

On one hand, I could just rewrite all of the code from those dependencies to bundle them with my gem and remove the dependency all together, but that seems a little tedious. Is there any way for me to simply include the gem dependencies directly in my gem, then wrap them in a module so my packaged versions don't conflict with the versions used by the rest of the application?

brightball
  • 923
  • 13
  • 11
  • maybe create a meta gem that depends precisely on all the various dependency versions of the sub-gems that work together? – rogerdpack Jul 09 '13 at 15:49

2 Answers2

1

I don't think what you want is possible via existing Ruby tools. However, if backwards-compatibility for you when relying on your dependency is purely a syntax/usage issue, and not a low-level difference between versions, then you don't have to import and maintain the old gem's code. You have another option: Create a "shim" layer in your gem that provides the functions you need from either new or old interface of the dependency.

In practice it might look like this, assuming by way of example that it was the constructor to the Thingy class that has changed:

module DependencyShim

  def new_Thingy( new_style_args )
    if thingy_is_new
      Thingy.new( new_style_args )
    else
      Thingy.new( convert_args_to_old_style( new_style_args ) )
    end
  end

  # convert_args_to_old_style() not shown

  private

  def thingy_is_old
    Thingy::VERSION < '1.3.4'
  end

  def thingy_is_new
    Thingy::VERSION >= '1.3.4'
  end
end

Better abstractions are very likely possible, but are difficult to predict as I don't know the nature of difference between old and new, and how tightly bound your code is to your dependency.

This is obviously painful if there are radical changes between versions, and your own gem uses the dependency heavily. But even then it may still be less painful than re-implementing and maintaining the dependency inside your own gem.

I would recommend looking at making your gem the most compatible with latest versions of your dependencies, and over the long term moving to deprecate support for the old dependencies, based on what you know of your user base. There may be good reasons for all involved to move away from the old dependency.

Neil Slater
  • 26,512
  • 6
  • 76
  • 94
0

Assuming you are using bundler, you can specify versions for dependencies in your Gemfile like this:

gem "my_dependency", "0.6.1"

There's a whole load of other options too such as 'version greater than X' etc. Read the bundler docs for more info.

omnikron
  • 2,211
  • 17
  • 30
  • I think the OP knows this, and is looking for what to do when version `1.0.1` is not compatible with their published gem. And ideally solve things in a way that means end users can still use version `1.0.1` in *the user's* project alongside the gem that doesn't want version `1.0.1`. AFAIK, this is either not possible, or quite difficult to achieve. – Neil Slater Jul 09 '13 at 12:51
  • But the whole idea is flawed - he says 'I also don't want to force people using my gem to have to use specific versions of the gems it depends on in the rest of their application' which is not the case, they would just need to have those versions _installed_ for his gem to use. – omnikron Jul 10 '13 at 10:03
  • Am I mistaken in thinking that the Gemfile.lock manages Gem dependencies within the entire application and that if my Gem requires an old version of Nokogiri that it would constrain the entire application to use that version of Nokogiri? That's always been my understanding of how Gem dependencies worked. – brightball Jul 10 '13 at 13:45
  • I apologise, that is actually correct, having done some reading it appears I have been labouring under a misapprehension - I guess I've just been lucky with my gems so far. Carry on! – omnikron Jul 10 '13 at 14:17