LE may not be activated in the presence of eventmachine in some circumstances
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.
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 ...
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.
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
You could also just re-implement require_relative if it isn't already defined; that would involve no load path mangling.
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 :)
The problem however are all those EM libraries that depend on EM. They should not.
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>
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