Ticket #471 (closed defect: duplicate)

Opened 11 months ago

Last modified 10 months ago

[PATCH] Kernel#dependency is broken in 0.5! Loading only from Merb.root / gems blocks loading other dependent gems from system.

Reported by: dcpark..@gmail.com Assigned to:
Priority: blocker Milestone: The Future
Component: Merb Keywords:
Cc:

Description

At least on my system. I put in a few simple puts to report where it ends up loading the files from. See the output -- for my app, I have these gems in the gem directory: haml-1.7.2, merb_datamapper-0.5, merb_datamapper-0.4.4, RedCloth?-3.0.4, ruby-openid-2.0.2, validatable-1.6.6. See the following results:

ORM Dependency merb_datamapper
Loading merb_datamapper:
Trying local...
Trying system...
ORM Dependency merb_datamapper Loaded!
Loading validatable:
Trying local...
Loading ruby_magic:
Trying local...
Trying system...
Trying library...
Loading RedCloth:
Trying local...
Loading ruby-openid:
Trying local...
Loading oauth:
Trying local...
Trying system...
Loading Application...

From those results I can see all gems loaded from their proper location, EXCEPT for merb_datamapper. It loaded from the system.

Also, past this point (as the system has merb_datamapper-0.5 and it should be fine), I'm getting an "uninitialized constant DataMapper?" error. Why/How could this be? Is the cause of both problems the same cause?? (something that raises a LoadError? would send it off to load the gem from the next source, the system).

Attachments

dependency_fix.patch (2.8 kB) - added by dcpark..@gmail.com on 01/31/08 10:52:43.
Solves all dependency / gems folder problems.

Change History

01/18/08 13:37:32 changed by dcpark..@gmail.com

I think I've found the problem -- when a gem in the local gems folder requires (dependency) a gem that is not in that gems folder, the second gem is not found, resulting in the first gem NOT loading from the gems folder.

01/18/08 14:02:57 changed by dcpark..@gmail.com

I'm wondering if we could simply make the gems folder take precedence over the rest... Reading the rdoc documentation -- when a gem is required, it could be any of the same version randomly. It sorts by name, then version, then floats ruby platform gems to the top. So if there are a few that are the same, it doesn't care. It looks like the best cure would be to overwrite the Gem::Specification#sort_obj method to include a test for installation_path == Merb.root / "gems". If I get it to work, I'll post a patch.

01/18/08 14:13:38 changed by dcpark..@gmail.com

I don't know how to test the success of this, but here's my suggestion -- run this so that Gem puts your Merb.root / "gems" gems at the top, then use the old-fashioned dependency method instead of the fancy new one.

class Gem::Specification
  def sort_obj
    .@name, installation_path == Merb.root / 'gems' ? -1 : 1, @version.to_ints, @new_platform == Gem::Platform::RUBY ? -1 : 1]
  end
end

01/21/08 07:54:22 changed by dcpark..@gmail.com

  • summary changed from use_orm does not load orm from the local gems folder to dependency cannot load gems in the gems directory dependent on gems NOT in the gems directory.
  • milestone changed from The Future to 0.5.2.

Ok, Monday rolls around, I've tested this out and it looks like all's good except for switching the -1 and the 1 in that example above. Replacing the top of the core_ext/kernel.rb file in merb core with the following code seems to work great:

module Gem
  class Specification
    def sort_obj
      .@name, installation_path == Merb.root / 'gems' ? 1 : -1, @version.to_ints, @new_platform == Gem::Platform::RUBY ? -1 : 1]
    end
  end
end

module Kernel
  # Loads the given string as a gem.
  # An optional second parameter of a version string can be specified and is passed to rubygems.
  # If rubygems cannot find the gem it requires the string as a library.
  
  # Note that this new version tries to load the file via ROOT/gems first before moving off to
  # the system gems (so if you have a lower version of a gem in ROOT/gems, it'll still get loaded)
  
  def dependency(name, *ver)
    begin
      Gem.activate(name, true, *ver)
      Merb.logger.info("#{Time.now.httpdate}: loading gem '#{name}' from #{__app_file_trace__.first} ...")
    rescue LoadError
      require name
    end
  end
  ...

Of course that "Gem" extension probably shouldn't go in kernel.rb, so I'll leave that up to whoever should make that decision. My testing shows that this works perfectly except for the following quirk: I had two versions of a gem in my gems folder, and it chose the earlier version. I didn't see it do that anywhere except in the gems directory, so as long as there is only one version of a gem installed in a gems directory, it's happy.

01/21/08 14:32:47 changed by dcpark..@gmail.com

  • priority changed from critical to major.

01/28/08 14:00:06 changed by iv..@gweezlebur.com

  • milestone changed from 0.5.2 to The Future.

01/28/08 14:06:18 changed by dcpark..@gmail.com

May I ask why "The Future"? I'd like to argue that this is rather an almost-critical bug. I know at least 3-4 people who aren't trying merb yet because of this bug. Rails developers are used to freezing vendor items (gems) in their project, and this bug essentially breaks the whole reason for the gems folder! Can this be included asap?

01/28/08 14:44:46 changed by iv..@gweezlebur.com

Because I'm releasing 0.5.3 today, and I don't feel good about putting this into it untested. This point release is probably the last 0.5.x release, so I'm moving all tickets on 0.5.x to The Future, unless they're getting included today.

If you can get some folks to test this patch before I release, I'm happy to consider including it.

Let's talk in #merb, if you're there.

01/31/08 08:11:16 changed by dcpark..@gmail.com

I just upgraded to merb-0.5.3, and a bunch of things broke. First of all ActiveSupport? was trying to load the Application constant, who knows why.. when I disabled ActiveSupport? from the project, it couldn't find the datamapper sessions plugin (which should be in merb_datamapper-0.5).

Anyway, all to say when I put this patch back in to 0.5.3, everything just jumped back on track! I hope more people test this soon!

01/31/08 10:52:43 changed by dcpark..@gmail.com

  • attachment dependency_fix.patch added.

Solves all dependency / gems folder problems.

01/31/08 10:53:09 changed by dcpark..@gmail.com

UPDATE - the Gems package really isn't written that well.

I found that it will drop out of its index all but reference to one gem of a certain name and version. So I added an overwrite of one more method that will ensure gems from the gems directory are not forgotten.

Here's an updated patch, rewritten with lots of study and digging behind it. Until rubygems undergoes a full rewrite, this patch will suffice. I'd like to suggest a "local gems" feature be added to the rubygems library. This patch is definitely reliable. Use it.

02/07/08 10:28:12 changed by jonmag..@gmail.com

This worked for me right away, thanks...

02/11/08 09:36:44 changed by dcpark..@gmail.com

  • priority changed from major to blocker.
  • summary changed from dependency cannot load gems in the gems directory dependent on gems NOT in the gems directory to [PATCH] Kernel.dependency is broken in 0.5! Loading only from Merb.root / gems blocks loading other dependent gems from system..

Sorry to be a bother, but is this going to be looked at and included soon? I do believe many people are having troubles with the latest merb release because of this problem -- everyone I know has (or would have, if I didn't direct them to this patch) reverted back to the previous merb release just because of this problem. Can I say it's a blocker? Who can update their projects that depend on local gems if this dependency loader seldom works at all?

I just closed a duplicate of this issue, #494

02/11/08 09:57:30 changed by dcpark..@gmail.com

  • summary changed from [PATCH] Kernel.dependency is broken in 0.5! Loading only from Merb.root / gems blocks loading other dependent gems from system. to [PATCH] Kernel#dependency is broken in 0.5! Loading only from Merb.root / gems blocks loading other dependent gems from system..

Also, I've contacted Eric Hodel of the RubyGems? project to ask about getting this feature built into RubyGems? instead of requiring it to be hacked in -- it's a useful feature for any project that uses gems, not just Merb.

02/11/08 13:41:43 changed by shayarne..@gmail.com

  • status changed from new to closed.
  • resolution set to duplicate.