Conflicting Ruby Stones

I need to use two stones in my project that require a PDF namespace: pdf-reader and htmldoc.

Is there a way to get them to play together? The only way I can think of is to rewrite my own version of htmldoc to give it a different namespace.

+6
ruby conflict rubygems
source share
4 answers

There is probably no elegant solution to the problem. If you really need two gems working side by side, I think your best option is to fork one of them (or maybe both) and use your fork. Here's how I do it:

  • If either the gem is hosted on Github, or its fork, or both are on the Github fork, this looks the least useful.
  • If not one gem is included in Github, see if you can access the source (the ability to capture it from a gem is an opportunity, but finding a real repository can be useful, as there may be other files that are not included in the gem) , and put it in storage on Github. Make sure the gem license permits this (which almost certainly does if it is one of the usual open source licenses).
  • Make your changes.
  • Make sure that there is a .gemspec file in the root of the repository, the next step will not work otherwise.
  • Use the Bundler to manage project dependencies. Instead of specifying a dependency on the library that you changed as

     gem 'the_gem' 

    specify it as follows:

     gem 'the_gem', :git => 'git://github.com/you/the_gem.git' 

    (but change the repository url to the actual one)

  • Send an email to the maintainer that you changed and ask him or her to consider merging your changes in the next version.

The Bundler really makes it easy to use alternative gemstones with minimal problems. I often remake stones, correct errors or add functions, change my Gemfile to my version, and then ask the maintainer to join in my changes. When, or if this happens, I simply change my Gemfile back to just reference the official version of the gem.

An alternative strategy, if the maintainer does not want to merge in your changes and you want to distribute your version to others, is to upgrade your version to Rubygems as a new gem, but in this case the gem name prefix with your name or some other line that identifies your stone as an option.

+2
source share

Basically, you cannot do anything. It is good practice in Ruby to use distinguished names in the top-level namespace for this reason, and you just stumbled upon two libraries that violate this practice.

The only thing you can do is use Kernel#load instead of Kernel#require . Kernel#load accepts an optional boolean argument that tells it to evaluate the file in an anonymous module. Please note, however, that this is in no way safe: it is entirely possible to explicitly put stuff into the top-level namespace (using something like module ::PDF ) and thus exit the anonymous module.

Note that the API is really crappy: load just returns true or false , as require does. (Actually, since load always loading, it always returns true .) It is not possible to actually get an anonymous module. You basically have to pull it out of ObjectSpace manually. Oh, and of course, since nothing refers to an anonymous module, this will collect garbage, so you need to not only rummage through the bowels of ObjectSpace to find the module, you will also have to swing the garbage collector.

Sometimes I want Ruby to have the right modular system like Newspeak, Standard ML or Racket.

+5
source share

I have heard of new functionality called refinements. It is designed to avoid two different attempts by monkeys, affecting the same class, causing problems, but I would see if this can help with your problem.

0
source share

I answered this in connection with fooobar.com/questions/878356 / ...

Regards, I do not agree with the answer above. Here is how I do it:

ruby -S gem list my_gem

 `*** LOCAL GEMS *** my_gem (1.0.1, 1.0.0, 0.0.2) ` 

ruby -S gem lock my_gem-1.0.0 > locklist.rb

which generates a dependency list for a specific version in the locklist

 require 'rubygems' gem 'my_gem', '= 1.0.0' gem 'gem_base', '= 1.0.0' gem 'rest-client', '= 1.7.2' gem 'savon', '= 1.1.0' gem 'addressable', '= 2.3.6' gem 'mime-types', '= 1.25.1' gem 'netrc', '= 0.11.0' 

now you can do load('locklist.rb') , which will load a specific version of the gem along with its dependencies. Look, ma, there is no Bundler.

0
source share

All Articles