This project is archived and is in readonly mode.
Gem dependencies inconsistently load rails/init.rb
-
DHH
- Assigned user set to Rick
-
Rick
- State changed from new to open
Okay, I'm seeing two issues here:
- Frozen gems aren't getting their specs loaded, so unpacked gems aren't getting their rails/init.rb files run.
- The system gem specs are still loaded, so their init.rb files are run.
-
Rick
- State changed from open to verified
Bruce, can you (and any other interested parties) try the commit from my rails fork? Assuming this works well, I'll push this to the main rails repo.
-
Bruce Williams
Rick; will give it a shot -- results shortly.
-
Bruce Williams
Rick, it looks like you've fixed the loading from both the unpacked and system gem when both are present, but autoloading doesn't seem to be functioning correctly (See #3 below).
Also,
rails/init.rbdoesn't seem to be loaded at all from unpacked gems when the system gem is not present (See #4 below).Testing notes: Generated a fresh app from
railties/bin/railsusing a clone of your fork, tossed the rails source in vendor/rails, and used the unpack_testing gem attached to the ticket. Please let me know if this seems like the wrong way to go about it.In vendor/plugins
(Just for reference). Expected result. This was working before.
bruce@riyah Development/bug-324 % ruby script/console
Loading development environment (Rails 2.1.0)
LOADING /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/rails/init.rb
LOADING /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/lib/unpack_testing.rb
LOADED /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/lib/unpack_testing.rb
LOADING /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/lib/unpack_testing/autoloaded_constant.rb
LOADED /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/lib/unpack_testing/autoloaded_constant.rb
LOADED /Users/bruce/Development/bug-324/vendor/plugins/unpack_testing/rails/init.rb
>>
#2, Plain gem dependency
Expected result.
rails/init.rbloaded, and autoloading ofUnpackTesting::AutoloadedConstantsucceeds. This was working before.bruce@riyah Development/bug-324 % ruby script/console
Loading development environment (Rails 2.1.0)
LOADING /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
LOADED /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
LOADING /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/rails/init.rb
LOADING /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/lib/unpack_testing/autoloaded_constant.rb
LOADED /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/lib/unpack_testing/autoloaded_constant.rb
LOADED /Library/Ruby/Gems/1.8/gems/unpack_testing-0.0.001/rails/init.rb
>>
#3, Unpacked, gem still present on system
rails/init.rbloaded from the right place, but autoloading ofUnpackTesting::AutoloadedConstantfails (looks like it's using a plainvendor/load path, incorrectly guessing the constant?)bruce@riyah Development/bug-324 % ruby script/console
Loading development environment (Rails 2.1.0)
LOADING /Users/bruce/Development/bug-324/vendor/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
LOADED /Users/bruce/Development/bug-324/vendor/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
LOADING /Users/bruce/Development/bug-324/vendor/gems/unpack_testing-0.0.001/rails/init.rb
/Users/bruce/Development/bug-324/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:116:in `qualified_const_defined?':NameError: "Gems::UnpackTesting-0.0.001::Lib::UnpackTesting" is not a valid constant name!
>>
#4, Unpacked, gem not present on system
rails/init.rbnot loaded at all.bruce@riyah Development/bug-324 % ruby script/console
Loading development environment (Rails 2.1.0)
LOADING /Users/bruce/Development/bug-324/vendor/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
LOADED /Users/bruce/Development/bug-324/vendor/gems/unpack_testing-0.0.001/lib/unpack_testing.rb
>>
-
Repository
- State changed from verified to resolved
(from [faad1e32a8ab81890018ba89d191607778830cf0]) Fix discrepancies with loading rails/init.rb from gems. [#324 state:resolved]
-
Rick
- Milestone cleared.
- State changed from resolved to open
-
Rick
- Milestone set to 2.1.1
-
Repository
- State changed from open to resolved
(from [e1bd75a92285c29269270e708e49d7cd5fabac36]) Fix discrepancies with loading rails/init.rb from gems. [#324 state:resolved]
-
Bruce Williams
As of 10c581a6deed66e8b62de6e7a3621a63de90baad (HEAD as of now), I'm still seeing the same behavior in unpacked gems as mentioned in my last comment. I also tested this against e1bd75a92285c29269270e708e49d7cd5fabac36 with the same results.
- When unpacked with the system gem still present, autoloading fails (attempts to build constants such as Gems::UnpackTesting-0.0.001::Lib::UnpackTesting)
- When unpacked without the system gem present, rails/init.rb isn't loaded.
Did your testing show different results? I'm generating a fresh app using railties/bin/rails and tossing the repo in at vendor/rails.
-
Jeremy Kemper
- State changed from resolved to open
I'm having the same issue with - in the constant name. Trying to autoload constants from an a path that doesn't convert into a module name.
-
Ramon Salvadó
Instead of unpacking gems we could just install them in vendor/gems using the gem command (or unpack could just do a gem install):
Ex: gem install -i gems activesupport activerecord (From RAILS_ROOT)
Then we could just do something:
Gem.path.unshift(RAILS_ROOT + "vendor/gems")This is how merb do it afaik, is there any reason for not doing it? seems better than the current way to me.
-
Bruce Williams
Ramon, if you think that's a better way, by all means add an enhancement ticket so it can be discussed.
The resolution of this issue (the breakage of a feature in 2.1) is a different concern.
-
Jeremy Kemper
- State changed from open to stale
No progress here. Someone needs to tackle it or it will be left behind.
-
Chad Woolley
This is a key feature. I personally don't care about unpacked gems, but I'd love to have plugins just work as external gems.
I also don't care about it working with config.gems. The sensible thing to me would be to process rails/init.rb for any activated gem which has a rails/init.rb - regardless of whether it was put on the load path via config.gems, preinitializer.rb, or manually via a gem() call. That seems the most logical, decoupled approach.
I can't commit, but I'll try to dig into this next time I have an itch related to it...
-
Rene Androsch
I'm sorry to see that this bug is marked stale - since it's a problem which happens at my deployment scenarios.
My workaround is at the moment to remove gems packaged into the application. => But I'd like to have fully consistent application deployments (means every application brings it's on rails + gems, so that there are zero dependencies on the host, besides a database connection).
-
Justin Marney
I think I figured out the reason why "#3 Unpacked, gem still present on system" is throwing an error. The current path to constant resolution convention assumes that directories under lib, plugins, and gems can be used as constant names. When a gem with a version number is unpacked the directory has the version number in it, causing the above problem. I have attached a patch that strips the version numbers out of the constant name. Of course, the patch also comes with a test :) Hopefully this will unstale this guy, because I am very interested in never using plugins again.
-
Justin Marney
Actually, as far as I can tell that patch also fixes #4. neat!
-
Wincent Colaiuta
Rails 2.1.1 is out and the changelog (http://gist.github.com/raw/8946/... mentions "Fix discrepancies with loading rails/init.rb from gems". I presume that refers to commit e1bd75a92285c29269270e708e49d7cd5fabac36 (http://github.com/rails/rails/co..., right?
Is it true then that the breakage that Bruce described is still present in the latest release?
-
Wincent Colaiuta
Just tested Justin's patch against 2.1.1.
In 2.1 with Haml 2.0.2 frozen into vendor/gems my spec suite runs fine. After upgrading to 2.1.1 "rake spec" fails with the following (didn't even get as far as running the app, I imagine it won't even boot):
rake aborted! "Gems::Haml-2.0.2::Lib" is not a valid constant name! (See full trace by running task with --trace)After applying the patch to 2.1.1 the spec suite runs fine again. Haven't yet established whether this happens to fix cases #3 and #4 referenced previously.
-
Justin Marney
@Wincent Just to clarify, the case in which your spec fails is 2.1.1 WITHOUT the patch. With the patch applied everything seems to work appropriately, right?
-
Wincent Colaiuta
Yes that's right Justin: 2.1 worked without the patch, 2.1.1 doesn't work without the patch.
-
Wincent Colaiuta
The plot thickens:
Rails 2.1.1, Haml 2.0.2 frozen into vendor/gems/, and the patch applied. Works fine until I delete the system-wide copy of Haml 2.0.2 (leaving the frozen one intact in vendor/gems/). Upon deleting Haml 2.0.2 gem from the system all attempts to run specs or launch the app yield:
uninitialized constant Rails::Initializer::SassI actually think that might be a separate problem, something about Haml itself seeing as I can't reproduce the problem with other gems. It seems like it wasn't designed to be frozen into vendor/gems/.
-
Wincent Colaiuta
Further testing reveals that "init.rb"/"rails/init.rb" are not getting evaluated in the frozen gem; "init.rb" does get evaluated when Haml is installed as a plugin at vendor/plugins/haml.
Related post to Haml group:
-
Justin Marney
@wincent make sure you check out: http://rails.lighthouseapp.com/p... which is a separate issue I created a patch for. I'll be testing haml with both of these patches and let you know what I find.
-
Justin Marney
@wincent I tested this with rails 2.1.1 and haml-2.0.3 with none of the patches applied and didn't run into any problems.
- system based haml installed, ran system rails/init.rb
- system based haml installed with frozen haml, ran frozen rails/init.rb
- no system based haml with frozen haml, ran frozen rails/init.rb
-
Wincent Colaiuta
Haml 2.0.3 just came out and I haven't tried it yet, so will do so.
I'm not surprised about "1" and "2" but I am a little surprised about "3", as I have other frozen gems that aren't installed on the system and their rails/init.rb didn't seem to be getting called. Will double check.
-
Wincent Colaiuta
Justin, I can't reproduce your findings. I just gave it a try with Rails 2.1.1 + the patch from this ticket and Haml 2.0.3:
- system based haml installed, ran system rails/init.rb
- system based haml installed with frozen haml, ran frozen rails/init.rb
- no system based haml with frozen haml, failed to run rails/init.rb
Also tried it with Rails 2.1.1, unpatched, a new Rails app with nothing but this config.gem line in the environment.rb:
config.gem 'haml', :version => '>= 2.0.3'- system based haml installed, ran system rails/init.rb
- system based haml installed with frozen haml, ran frozen rails/init.rb
- no system based haml with frozen haml, failed to run rails/init.rb
And a fourth option:
- no system based haml and no frozen haml, correctly aborts with "Missing these required gems..."
Also note that in 2.1.1 "rake gems:unpack" doesn't work due to bug #1003; I could only complete the above tests by applying the patch from that ticket.
-
Justin Marney
@wincent How are you testing to see if init.rb was run or not. I want to make sure we are doing the same thing.
-
Wincent Colaiuta
- Tag changed from 2.1-stable, bug, dependencies, edge to 2.1-stable, bug, dependencies, edge, patch
I'm testing by sticking something like this in rails/init.rb:
raise "derailed!"When rails/init.rb gets evaluated the exception is raised and whatever I'm doing (script/console, rake spec etc) aborts.
In any case, I've taken the time to grok the gem loading code a bit and I've come up with a patch that fixes things for me at least.
The key lies in railties/lib/rails/plugin/locator.rb. Basically, only stuff which has a Gem::Specification will have its rails/init.rb evaluated because everything else gets filtered out.
It appears that any system-installed gem will have a Gem::Specification set up for it by RubyGems when the "gem" method is called from add_load_paths in railties/lib/rails/gem_dependency.rb.
On the other hand, if a gem is frozen then it winds up going through the other code path in add_load_paths; the frozen "lib" (and possibly "ext") paths are added to the load path but "gem" is never called and a spec is never set up.
As Rick commented back in June, "Frozen gems aren't getting their specs loaded, so unpacked gems aren't getting their rails/init.rb files run."
So my patch just adds a Gem::Specification for all such frozen gems and now rails/init.rb does indeed get called for them. I chose to put this in add_load_paths because that's where the non-frozen gems end up getting their Gem::Specifications too (by the RubyGems "gem" method).
-
Magnus Bergmark
- Tag changed from 2.1-stable, bug, dependencies, edge, patch to 2.1-stable, bug, dependencies, edge, patch
Is there anything happening with this issue?
-
Matt Jones
Can somebody double check that this works now? The changes from #1128 should have removed any inconsistencies. (the 'frozen gem without system gem' case should work)
-
Jeremy Kemper
- Milestone changed from 2.1.1 to 2.1.3
-
Wincent Colaiuta
Just updated an application from 2.1.1 to 2.1.2 and can confirm that it's still a problem in the latest Rails release (2.1.2). Also tested that the patch I posted back in September fixes the problem in 2.1.2 as well, and it does.
Any chance of getting it applied before 2.2 goes final? (Later today when I get some time I hope to test the 2.2 release candidate and see if the problem is still present there.)
-
Wincent Colaiuta
I should also add that Justin's patch is still needed to correct errors like:
"Gems::Haml-2.0.3::Lib" is not a valid constant name!My patch handles a separate issue (for example, when Haml is frozen into vendor/gems and not present elsewhere on the system):
uninitialized constant Rails::Initializer::Sass
