EventMachine-LE icon indicating copy to clipboard operation
EventMachine-LE copied to clipboard

LE may not be activated in the presence of eventmachine in some circumstances

Open mpalmer opened this issue 9 years ago • 8 comments

Short version: Depending on the order in which gems are activated, it is possible to end up in the situation where eventmachine is preferred over eventmachine-le, causing much wailing and gnashing of teeth. Modifying eventmachine-le.rb to include $LOAD_PATH.delete_if { |d| d =~ /\/eventmachine-\d/ } before require 'eventmachine' fixes things, although there's possibly a more graceful way.

Longer version: When a gem is activated, all its dependencies are activated too. This means that if you have any gems that depend on eventmachine, then it will end up in $LOAD_PATH, likely before any require statements (such as require 'eventmachine-le') are run.

The order of the entries in $LOAD_PATH is "last-activated-first" -- that is, if a gem activates eventmachine-le before it activates a gem that depends on eventmachine, then eventmachine wins, and eventmachine-le's code never gets loaded.

To complete the trifecta, running gem 'eventmachine-le' when eventmachine-le has already been activated does nothing -- it'd be nice if it "promoted" that gem's load paths to the first entries in $LOAD_PATH, but unfortunately, it does not.

mpalmer avatar Feb 11 '15 02:02 mpalmer

Hi, that is supposed to be documented in the README:

  • https://github.com/ibc/EventMachine-LE#usage

Is that wrong? I would not like to mangle $LOAD_PATH ...

ibc avatar Feb 11 '15 13:02 ibc

The README isn't wrong, per se -- as long as the eventmachine gem hasn't already been activated, what's in the README will work just fine. Unfortunately, when a gem gets activated, all its dependencies get activated, and so if you activate a gem which depends on eventmachine, it'll end up in the load path. If you happened to previously activate eventmachine-le (say, because you activated a gem which depends on it -- such as the gem you're running your command from) then eventmachine will be used, not eventmachine-le.

Non-load-path-mangling alternatives are fairly thin on the ground. If you wanted to drop 1.8 support, you could use require_relative everywhere throughout; that would solve the problem. You could temporarily mangle the load path, by unshifting the eventmachine-le gem directory onto the load path, requiring eventmachine, and then shifting it back off again afterwards. They're the only options I can think of at the moment.

mpalmer avatar Feb 11 '15 20:02 mpalmer

Non-load-path-mangling alternatives are fairly thin on the ground. If you wanted to drop 1.8 support, you could use |require_relative| everywhere throughout; that would solve the problem. You could temporarily mangle the load path, by unshifting the eventmachine-le gem directory onto the load path, requiring eventmachine, and then shifting it back off again afterwards. They're the only options I can think of at the moment.

We could define a "require_relative_ele" that simply maps to require_relative on a modern Ruby and employs load-path mangling on 1.8.

Grüße, Carsten

cabo avatar Feb 11 '15 20:02 cabo

You could also just re-implement require_relative if it isn't already defined; that would involve no load path mangling.

mpalmer avatar Feb 11 '15 21:02 mpalmer

VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_raise(rb_eLoadError, "cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

Should not be difficult to implement in Ruby :)

ibc avatar Feb 11 '15 23:02 ibc

The problem however are all those EM libraries that depend on EM. They should not.

ibc avatar Feb 11 '15 23:02 ibc

Well, until Rubygems has a concept of either "virtual packages" or "OR" dependencies, it's a bit hard for a gem to declare a dependency in a way other than on eventmachine -- unless you're talking about going round and convincing every gem to depend on eventmachine-le instead... <grin>

mpalmer avatar Feb 12 '15 00:02 mpalmer

for future readers of this ticket the fix we've put in place is slightly different from @mpalmer's:

$LOAD_PATH.delete_if { |p| p.to_s =~ /eventmachine-\d/ }

The $LOAD_PATH can be a Pathname

filterfish avatar Apr 21 '15 05:04 filterfish