1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix backwards compatibility with Rails 3 apps.

When we removed script/rails and introduced bin/rails, we accidentally
introduced a regression. If you install Rails 4 as a gem, then try to do
something in a Rails 3 application:

    $ rails g

This will throw the 'please type rails new foo' message rather than the
proper generator documentation message. This is because older apps don't
have bin/rails.

Therefore, we now *prefer* bin/rails, but still search for script/rails,
and exec the one we find.
This commit is contained in:
Steve Klabnik 2013-02-22 14:09:43 -05:00
parent 31f807c7aa
commit c5a9c02e01
3 changed files with 52 additions and 40 deletions

View file

@ -3,12 +3,16 @@ require 'pathname'
module Rails
module AppRailsLoader
RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
EXECUTABLE = 'bin/rails'
EXECUTABLES = ['bin/rails', 'script/rails']
def self.exec_app_rails
cwd = Dir.pwd
return unless in_rails_application_or_engine? || in_rails_application_or_engine_subdirectory?
exec RUBY, EXECUTABLE, *ARGV if in_rails_application_or_engine?
cwd = Dir.pwd
exe = find_executable
exe ||= find_executable_in_parent_path
return unless exe
exec RUBY, exe, *ARGV if find_executable
Dir.chdir("..") do
# Recurse in a chdir block: if the search fails we want to be sure
# the application is generated in the original working directory.
@ -18,12 +22,16 @@ module Rails
# could not chdir, no problem just return
end
def self.in_rails_application_or_engine?
File.exists?(EXECUTABLE) && File.read(EXECUTABLE) =~ /(APP|ENGINE)_PATH/
def self.find_executable
EXECUTABLES.find do |exe|
File.exists?(exe) && File.read(exe) =~ /(APP|ENGINE)_PATH/
end
end
def self.in_rails_application_or_engine_subdirectory?(path = Pathname.new(Dir.pwd))
File.exists?(File.join(path, EXECUTABLE)) || !path.root? && in_rails_application_or_engine_subdirectory?(path.parent)
def self.find_executable_in_parent_path(path = Pathname.new(Dir.pwd))
EXECUTABLES.find do |exe|
File.exists?(File.join(path, exe)) || !path.root? && find_executable_in_parent_path(path.parent)
end
end
end
end

View file

@ -3,9 +3,6 @@ require 'rails/app_rails_loader'
# If we are inside a Rails application this method performs an exec and thus
# the rest of this script is not run.
#
# TODO: when we hit this, advise adding ./bin to $PATH instead. Then the
# app's `rails` executable is run immediately.
Rails::AppRailsLoader.exec_app_rails
require 'rails/ruby_version_check'

View file

@ -2,40 +2,47 @@ require 'abstract_unit'
require 'rails/app_rails_loader'
class AppRailsLoaderTest < ActiveSupport::TestCase
test "is in a rails application if bin/rails exists and contains APP_PATH" do
File.stubs(:exists?).returns(true)
File.stubs(:read).with('bin/rails').returns('APP_PATH')
assert Rails::AppRailsLoader.in_rails_application_or_engine?
setup do
File.stubs(:exists?).returns(false)
end
test "is not in a rails application if bin/rails exists but doesn't contain APP_PATH" do
File.stubs(:exists?).returns(true)
File.stubs(:read).with('bin/rails').returns('railties bin/rails')
assert !Rails::AppRailsLoader.in_rails_application_or_engine?
end
['bin/rails', 'script/rails'].each do |exe|
test "is in a rails application if #{exe} exists and contains APP_PATH" do
File.stubs(:exists?).with(exe).returns(true)
File.stubs(:read).with(exe).returns('APP_PATH')
assert Rails::AppRailsLoader.find_executable
end
test "is in a rails application if parent directory has bin/rails containing APP_PATH" do
File.stubs(:exists?).with("/foo/bar/bin/rails").returns(false)
File.stubs(:exists?).with("/foo/bin/rails").returns(true)
File.stubs(:read).with('/foo/bin/rails').returns('APP_PATH')
assert Rails::AppRailsLoader.in_rails_application_or_engine_subdirectory?(Pathname.new("/foo/bar"))
end
test "is not in a rails application if #{exe} exists but doesn't contain APP_PATH" do
File.stubs(:exists?).with(exe).returns(true)
File.stubs(:read).with(exe).returns("railties #{exe}")
assert !Rails::AppRailsLoader.find_executable
end
test "is not in a rails application if at the root directory and doesn't have bin/rails" do
Pathname.any_instance.stubs(:root?).returns true
assert !Rails::AppRailsLoader.in_rails_application_or_engine?
end
test "is in a rails application if parent directory has #{exe} containing APP_PATH" do
File.stubs(:exists?).with("/foo/bar/#{exe}").returns(false)
File.stubs(:exists?).with("/foo/#{exe}").returns(true)
File.stubs(:read).with("/foo/#{exe}").returns('APP_PATH')
assert Rails::AppRailsLoader.find_executable_in_parent_path(Pathname.new("/foo/bar"))
end
test "is in a rails engine if parent directory has bin/rails containing ENGINE_PATH" do
File.stubs(:exists?).with("/foo/bar/bin/rails").returns(false)
File.stubs(:exists?).with("/foo/bin/rails").returns(true)
File.stubs(:read).with('/foo/bin/rails').returns('ENGINE_PATH')
assert Rails::AppRailsLoader.in_rails_application_or_engine_subdirectory?(Pathname.new("/foo/bar"))
end
test "is not in a rails application if at the root directory and doesn't have #{exe}" do
Pathname.any_instance.stubs(:root?).returns true
assert !Rails::AppRailsLoader.find_executable
end
test "is in a rails engine if bin/rails exists containing ENGINE_PATH" do
File.stubs(:exists?).returns(true)
File.stubs(:read).with('bin/rails').returns('ENGINE_PATH')
assert Rails::AppRailsLoader.in_rails_application_or_engine?
test "is in a rails engine if parent directory has #{exe} containing ENGINE_PATH" do
File.stubs(:exists?).with("/foo/bar/#{exe}").returns(false)
File.stubs(:exists?).with("/foo/#{exe}").returns(true)
File.stubs(:read).with("/foo/#{exe}").returns('ENGINE_PATH')
assert Rails::AppRailsLoader.find_executable_in_parent_path(Pathname.new("/foo/bar"))
end
test "is in a rails engine if #{exe} exists containing ENGINE_PATH" do
File.stubs(:exists?).with(exe).returns(true)
File.stubs(:read).with(exe).returns('ENGINE_PATH')
assert Rails::AppRailsLoader.find_executable
end
end
end