This project is archived and is in readonly mode.
Having Rails 2.3pre or Rack 1.1 installed breaks Rails 2.x
Reported by Hongli Lai | February 22nd, 2010 @ 09:43 AM
Rails 2.x and earlier currently specifies 'rack ~> 1.0.0' as gem dependency. This can cause problems in the following environment:
- Thin is installed with RubyGems.
- Rails 2.x is installed with RubyGems.
- Rails 3.0pre is installed with RubyGems (which pulls in Rack 1.1).
Thin has a dependency on 'rack', no specific version. However if Rack 1.1 is installed then starting Thin will automatically activate the latest version of Rack, 1.1. Rails's environment.rb tries to activate the Rails gems, but this fails at activating Rack 1.0.x because 1.1 is already activated.
Furthermore, boot.rb mistakenly thinks that this error means Rails isn't installed, so you get a console output like this:
[hongli@Minato foobar.test]$ thin start -S `pwd`/thin.sock -e production
>> Using rails adapter
Missing the Rails 2.3.5 gem. Please `gem install -v=2.3.5 rails`,
update your RAILS_GEM_VERSION setting in config/environment.rb for the
Rails version you do have installed, or comment out RAILS_GEM_VERSION to
use the latest version installed.
The offending code is in boot.rb's load_rails_gem:
def load_rails_gem
if version = self.class.gem_version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
end
If we put a 'puts load_error' in the rescue block then we'll see
that the actual error is something along the lines of:
can't activate rack (~> 1.0.0, runtime) for ["actionpack-2.3.5",
"rails-2.3.5"], already activated rack-1.1.0 for ["thin-1.2.5"]
Phusion Passenger is suffering from the same problem since it specifies Rack as a gem dependency too.
This problem can be solved by changing Rails's Rack dependency to "rack >= 1.0.0".
Comments and changes to this ticket
-
Maximilian Schulz February 22nd, 2010 @ 10:23 AM
I am not sure about the way thin is handling the problem, but I had the same with Passenger. I use the past tense, as the problem can be solved by removing the config.ru file from your application root. As specified in the passenger 2.2.9 release notes, the default behavior was changed. Specifically, passenger's rails adapter priority is now lower than the default rack adapter's. But be removing the config.ru file, the rails adapter will kick in and will load rack 1.0.1 and your rails 2.3.5 apps will load fine again.
Passenger Configuration:
- 2.3.5 apps: remove config.ru
- 3.0.0 apps: keep config.ru
-
Hongli Lai February 22nd, 2010 @ 11:33 AM
After speaking to Yehuda (http://groups.google.com/group/rubyonrails-core/browse_thread/threa...) and giving it more thought I think the fix should be in RubyGems, not in Rack or in Rails.
I've considered the possibility of splitting the Rack library into two portions, one that only the web server uses and one that only the web app uses. However this would make it impossible for the web server to modify the app's behavior. For example Thin inserts a middleware that utilizes Rack::Request in order to generate various statistics.
Phusion Passenger happens to accidentally work around the issue by executing its spawn server without the RubyGems wrapper binary, so it doesn't activate Rack when loading regular Rails apps.
I think RubyGems should not pre-activate dependencies for which no version specification is given. This would allow Thin to implement an option to tell it which Rack version to load.
-
Hongli Lai February 22nd, 2010 @ 11:55 AM
I filed a RubyGems issue: http://rubyforge.org/tracker/index.php?func=detail&aid=27867&am...
-
Saimon Moore April 20th, 2010 @ 12:02 PM
Is there any other workaround apart from physically modifying rails/actionpack/lib/action_controller.rb?
-
Hongli Lai April 21st, 2010 @ 08:50 AM
You can modify the Mongrel/Thin/etc startup script to explicitly require Rack 1.0. Phusion Passenger does not need modification and isn't affected by the issue.
-
Saimon Moore April 21st, 2010 @ 09:23 AM
Hongli, I think I know what happened. I'm using rvm to handle my
rubies. I have 1.9.1-p378 installed. I also use a gemset for each
application. Recently I upgraded rvm and had to reinstall all my gems.
I first installed passenger under 1.9.1 (without a gemset so that
further minor updates to 1.9.1 wouldn't require updating passenger
too). Since passenger has a dependency on rack (> 0), it installed
rack 1.1.0 in the 1.9.1 gemset (which is automatically added to the
gem path for any sub gem sets. In my application's gemset, I then
reinstalled rack 1.0.1 not realizing that rack 1.1.0 had been
installed in the 1.9.1 gemset. You can guess the rest. I've now
removed rack 1.1.0 gem and it's working fine..Thanks...
It's a pain though all of this. Someone needs to find a decent solution.
-
raggi August 21st, 2010 @ 08:03 PM
Hongli sorry, but there's issues with your RubyGems suggestion, specifically, activation is actually different from require, as activation specifies a specific gem from the gem namespace, whereas require picks arbitrarily from the filesystem space within all gems (ordered by alpha and version). There's no better way for us to do that, and as such not activating at the appropriate time could lead to require loading something unrelated. This would therefore be introducing a bug into RubyGems.
The correct way to solve this issue is to make point releases with appropriate dependency sets.
-
Ryan Bigg October 9th, 2010 @ 10:00 PM
- Tag cleared.
- Importance changed from to Low
Automatic cleanup of spam.
-
David Trasbo October 10th, 2010 @ 03:10 PM
- State changed from new to wontfix
As for the issue of telling users that the Rails gem is missing, when it might not actually be the case, I committed a fix a while back: http://github.com/rails/rails/commit/d0d10f51d7b2edea94a00291d79cad...
As for the other issue: That was actually the main reason Bundler was created. It's a fundamental architectural flaw that will definitely not be fixed in 2.3. You have three options:
- Use RVM to isolate gems for each of your applications, thus
preventing the need of having multiple versions of the same
gem.
- Use Bundler which, as mentioned, was created to solve this
specific problem.
- Or: Upgrade to Rails 3, which uses Bundler by default.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>