aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
authorCarl Lerche & Yehuda Katz <wycats@gmail.com>2009-04-13 15:18:45 -0700
committerCarl Lerche & Yehuda Katz <wycats@gmail.com>2009-04-13 15:18:45 -0700
commit906aebceedb95d8caa6db6314bc90f605bdfaf2b (patch)
tree5abc86bb6709b20df7cb5f4d1750b27c641dca4b /railties/lib
parent2036d3ba75da1a0f3061bf5a33c89e2b2eaff420 (diff)
parentc877857d59554d78dbf45f5f9fcaafb8badec4e2 (diff)
downloadrails-906aebceedb95d8caa6db6314bc90f605bdfaf2b.tar.gz
rails-906aebceedb95d8caa6db6314bc90f605bdfaf2b.tar.bz2
rails-906aebceedb95d8caa6db6314bc90f605bdfaf2b.zip
Bring abstract_controller up to date with rails/master
Resolved all the conflicts since 2.3.0 -> HEAD. Following is a list of commits that could not be applied cleanly or are obviated with the abstract_controller refactor. They all need to be revisited to ensure that fixes made in 2.3 do not reappear in 3.0: 2259ecf368e6a6715966f69216e3ee86bf1a82a7 AR not available * This will be reimplemented with ActionORM or equivalent 06182ea02e92afad579998aa80144588e8865ac3 implicitly rendering a js response should not use the default layout [#1844 state:resolved] * This will be handled generically 893e9eb99504705419ad6edac14d00e71cef5f12 Improve view rendering performance in development mode and reinstate template recompiling in production [#1909 state:resolved] * We will need to reimplement rails-dev-boost on top of the refactor; the changes here are very implementation specific and cannot be cleanly applied. The following commits are implicated: 199e750d46c04970b5e7684998d09405648ecbd4 3942cb406e1d5db0ac00e03153809cc8dc4cc4db f8ea9f85d4f1e3e6f3b5d895bef6b013aa4b0690 e3b166aab37ddc2fbab030b146eb61713b91bf55 ae9f258e03c9fd5088da12c1c6cd216cc89a01f7 44423126c6f6133a1d9cf1d0832b527e8711d40f 0cb020b4d6d838025859bd60fb8151c8e21b8e84 workaround for picking layouts based on wrong view_paths [#1974 state:resolved] * The specifics of this commit no longer apply. Since it is a two-line commit, we will reimplement this change. 8c5cc66a831aadb159f3daaffa4208064c30af0e make action_controller/layouts pick templates from the current instance's view_paths instead of the class view_paths [#1974 state:resolved] * This does not apply at all. It should be trivial to apply the feature to the reimplemented ActionController::Base. 87e8b162463f13bd50d27398f020769460a770e3 fix HTML fallback for explicit templates [#2052 state:resolved] * There were a number of patches related to this that simply compounded each other. Basically none of them apply cleanly, and the underlying issue needs to be revisited. After discussing the underlying problem with Koz, we will defer these fixes for further discussion.
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/commands/plugin.rb453
-rw-r--r--railties/lib/commands/server.rb19
-rw-r--r--railties/lib/console_app.rb5
-rw-r--r--railties/lib/fcgi_handler.rb22
-rw-r--r--railties/lib/initializer.rb51
-rw-r--r--railties/lib/rails/backtrace_cleaner.rb23
-rw-r--r--railties/lib/rails/gem_dependency.rb218
-rw-r--r--railties/lib/rails/plugin.rb8
-rw-r--r--railties/lib/rails/plugin/loader.rb59
-rw-r--r--railties/lib/rails/rack/metal.rb27
-rw-r--r--railties/lib/rails/rack/static.rb17
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/lib/rails_generator/commands.rb8
-rw-r--r--railties/lib/rails_generator/generators/applications/app/template_runner.rb42
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb2
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb8
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb2
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb4
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb4
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb4
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb2
-rw-r--r--railties/lib/tasks/databases.rake1
-rw-r--r--railties/lib/tasks/documentation.rake11
-rw-r--r--railties/lib/tasks/gems.rake81
-rw-r--r--railties/lib/tasks/testing.rake2
25 files changed, 389 insertions, 686 deletions
diff --git a/railties/lib/commands/plugin.rb b/railties/lib/commands/plugin.rb
index 9ff4739562..3d76bcc73f 100644
--- a/railties/lib/commands/plugin.rb
+++ b/railties/lib/commands/plugin.rb
@@ -1,47 +1,8 @@
# Rails Plugin Manager.
-#
-# Listing available plugins:
-#
-# $ ./script/plugin list
-# continuous_builder http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder
-# asset_timestamping http://svn.aviditybytes.com/rails/plugins/asset_timestamping
-# enumerations_mixin http://svn.protocool.com/rails/plugins/enumerations_mixin/trunk
-# calculations http://techno-weenie.net/svn/projects/calculations/
-# ...
#
# Installing plugins:
#
# $ ./script/plugin install continuous_builder asset_timestamping
-#
-# Finding Repositories:
-#
-# $ ./script/plugin discover
-#
-# Adding Repositories:
-#
-# $ ./script/plugin source http://svn.protocool.com/rails/plugins/
-#
-# How it works:
-#
-# * Maintains a list of subversion repositories that are assumed to have
-# a plugin directory structure. Manage them with the (source, unsource,
-# and sources commands)
-#
-# * The discover command scrapes the following page for things that
-# look like subversion repositories with plugins:
-# http://wiki.rubyonrails.org/rails/pages/Plugins
-#
-# * Unless you specify that you want to use svn, script/plugin uses plain old
-# HTTP for downloads. The following bullets are true if you specify
-# that you want to use svn.
-#
-# * If `vendor/plugins` is under subversion control, the script will
-# modify the svn:externals property and perform an update. You can
-# use normal subversion commands to keep the plugins up to date.
-#
-# * Or, if `vendor/plugins` is not under subversion control, the
-# plugin is pulled via `svn checkout` or `svn export` but looks
-# exactly the same.
#
# Specifying revisions:
#
@@ -134,7 +95,8 @@ class RailsEnvironment
def externals
return [] unless use_externals?
ext = `svn propget svn:externals "#{root}/vendor/plugins"`
- ext.reject{ |line| line.strip == '' }.map do |line|
+ lines = ext.respond_to?(:lines) ? ext.lines : ext
+ lines.reject{ |line| line.strip == '' }.map do |line|
line.strip.split(/\s+/, 2)
end
end
@@ -155,13 +117,13 @@ end
class Plugin
attr_reader :name, :uri
- def initialize(uri, name=nil)
+ def initialize(uri, name = nil)
@uri = uri
guess_name(uri)
end
def self.find(name)
- name =~ /\// ? new(name) : Repositories.instance.find_plugin(name)
+ new(name)
end
def to_s
@@ -207,10 +169,13 @@ class Plugin
else
puts "Plugin doesn't exist: #{path}"
end
- # clean up svn:externals
- externals = rails_env.externals
- externals.reject!{|n,u| name == n or name == u}
- rails_env.externals = externals
+
+ if rails_env.use_externals?
+ # clean up svn:externals
+ externals = rails_env.externals
+ externals.reject!{|n,u| name == n or name == u}
+ rails_env.externals = externals
+ end
end
def info
@@ -278,8 +243,8 @@ class Plugin
base_cmd += " #{options[:revision]}" if options[:revision]
puts base_cmd if $verbose
if system(base_cmd)
- puts "removing: .git" if $verbose
- rm_rf ".git"
+ puts "removing: .git .gitignore" if $verbose
+ rm_rf %w(.git .gitignore)
else
rm_rf install_path
end
@@ -309,129 +274,6 @@ class Plugin
end
end
-class Repositories
- include Enumerable
-
- def initialize(cache_file = File.join(find_home, ".rails-plugin-sources"))
- @cache_file = File.expand_path(cache_file)
- load!
- end
-
- def each(&block)
- @repositories.each(&block)
- end
-
- def add(uri)
- unless find{|repo| repo.uri == uri }
- @repositories.push(Repository.new(uri)).last
- end
- end
-
- def remove(uri)
- @repositories.reject!{|repo| repo.uri == uri}
- end
-
- def exist?(uri)
- @repositories.detect{|repo| repo.uri == uri }
- end
-
- def all
- @repositories
- end
-
- def find_plugin(name)
- @repositories.each do |repo|
- repo.each do |plugin|
- return plugin if plugin.name == name
- end
- end
- return nil
- end
-
- def load!
- contents = File.exist?(@cache_file) ? File.read(@cache_file) : defaults
- contents = defaults if contents.empty?
- @repositories = contents.split(/\n/).reject do |line|
- line =~ /^\s*#/ or line =~ /^\s*$/
- end.map { |source| Repository.new(source.strip) }
- end
-
- def save
- File.open(@cache_file, 'w') do |f|
- each do |repo|
- f.write(repo.uri)
- f.write("\n")
- end
- end
- end
-
- def defaults
- <<-DEFAULTS
- http://dev.rubyonrails.com/svn/rails/plugins/
- DEFAULTS
- end
-
- def find_home
- ['HOME', 'USERPROFILE'].each do |homekey|
- return ENV[homekey] if ENV[homekey]
- end
- if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
- return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
- end
- begin
- File.expand_path("~")
- rescue StandardError => ex
- if File::ALT_SEPARATOR
- "C:/"
- else
- "/"
- end
- end
- end
-
- def self.instance
- @instance ||= Repositories.new
- end
-
- def self.each(&block)
- self.instance.each(&block)
- end
-end
-
-class Repository
- include Enumerable
- attr_reader :uri, :plugins
-
- def initialize(uri)
- @uri = uri.chomp('/') << "/"
- @plugins = nil
- end
-
- def plugins
- unless @plugins
- if $verbose
- puts "Discovering plugins in #{@uri}"
- puts index
- end
-
- @plugins = index.reject{ |line| line !~ /\/$/ }
- @plugins.map! { |name| Plugin.new(File.join(@uri, name), name) }
- end
-
- @plugins
- end
-
- def each(&block)
- plugins.each(&block)
- end
-
- private
- def index
- @index ||= RecursiveHTTPFetcher.new(@uri).ls
- end
-end
-
-
# load default environment and parse arguments
require 'optparse'
module Commands
@@ -471,14 +313,8 @@ module Commands
o.separator ""
o.separator "COMMANDS"
- o.separator " discover Discover plugin repositories."
- o.separator " list List available plugins."
o.separator " install Install plugin(s) from known repositories or URLs."
- o.separator " update Update installed plugins."
o.separator " remove Uninstall plugins."
- o.separator " source Add a plugin source repository."
- o.separator " unsource Remove a plugin repository."
- o.separator " sources List currently configured plugin repositories."
o.separator ""
o.separator "EXAMPLES"
@@ -490,20 +326,6 @@ module Commands
o.separator " #{@script_name} install git://github.com/SomeGuy/my_awesome_plugin.git\n"
o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
o.separator " #{@script_name} install -x continuous_builder\n"
- o.separator " List all available plugins:"
- o.separator " #{@script_name} list\n"
- o.separator " List plugins in the specified repository:"
- o.separator " #{@script_name} list --source=http://dev.rubyonrails.com/svn/rails/plugins/\n"
- o.separator " Discover and prompt to add new repositories:"
- o.separator " #{@script_name} discover\n"
- o.separator " Discover new repositories but just list them, don't add anything:"
- o.separator " #{@script_name} discover -l\n"
- o.separator " Add a new repository to the source list:"
- o.separator " #{@script_name} source http://dev.rubyonrails.com/svn/rails/plugins/\n"
- o.separator " Remove a repository from the source list:"
- o.separator " #{@script_name} unsource http://dev.rubyonrails.com/svn/rails/plugins/\n"
- o.separator " Show currently configured repositories:"
- o.separator " #{@script_name} sources\n"
end
end
@@ -512,7 +334,7 @@ module Commands
options.parse!(general)
command = general.shift
- if command =~ /^(list|discover|install|source|unsource|sources|remove|update|info)$/
+ if command =~ /^(install|remove)$/
command = Commands.const_get(command.capitalize).new(self)
command.parse!(sub)
else
@@ -534,218 +356,6 @@ module Commands
end
end
-
- class List
- def initialize(base_command)
- @base_command = base_command
- @sources = []
- @local = false
- @remote = true
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} list [OPTIONS] [PATTERN]"
- o.define_head "List available plugins."
- o.separator ""
- o.separator "Options:"
- o.separator ""
- o.on( "-s", "--source=URL1,URL2", Array,
- "Use the specified plugin repositories.") {|sources| @sources = sources}
- o.on( "--local",
- "List locally installed plugins.") {|local| @local, @remote = local, false}
- o.on( "--remote",
- "List remotely available plugins. This is the default behavior",
- "unless --local is provided.") {|remote| @remote = remote}
- end
- end
-
- def parse!(args)
- options.order!(args)
- unless @sources.empty?
- @sources.map!{ |uri| Repository.new(uri) }
- else
- @sources = Repositories.instance.all
- end
- if @remote
- @sources.map{|r| r.plugins}.flatten.each do |plugin|
- if @local or !plugin.installed?
- puts plugin.to_s
- end
- end
- else
- cd "#{@base_command.environment.root}/vendor/plugins"
- Dir["*"].select{|p| File.directory?(p)}.each do |name|
- puts name
- end
- end
- end
- end
-
-
- class Sources
- def initialize(base_command)
- @base_command = base_command
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} sources [OPTIONS] [PATTERN]"
- o.define_head "List configured plugin repositories."
- o.separator ""
- o.separator "Options:"
- o.separator ""
- o.on( "-c", "--check",
- "Report status of repository.") { |sources| @sources = sources}
- end
- end
-
- def parse!(args)
- options.parse!(args)
- Repositories.each do |repo|
- puts repo.uri
- end
- end
- end
-
-
- class Source
- def initialize(base_command)
- @base_command = base_command
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} source REPOSITORY [REPOSITORY [REPOSITORY]...]"
- o.define_head "Add new repositories to the default search list."
- end
- end
-
- def parse!(args)
- options.parse!(args)
- count = 0
- args.each do |uri|
- if Repositories.instance.add(uri)
- puts "added: #{uri.ljust(50)}" if $verbose
- count += 1
- else
- puts "failed: #{uri.ljust(50)}"
- end
- end
- Repositories.instance.save
- puts "Added #{count} repositories."
- end
- end
-
-
- class Unsource
- def initialize(base_command)
- @base_command = base_command
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} unsource URI [URI [URI]...]"
- o.define_head "Remove repositories from the default search list."
- o.separator ""
- o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
- end
- end
-
- def parse!(args)
- options.parse!(args)
- count = 0
- args.each do |uri|
- if Repositories.instance.remove(uri)
- count += 1
- puts "removed: #{uri.ljust(50)}"
- else
- puts "failed: #{uri.ljust(50)}"
- end
- end
- Repositories.instance.save
- puts "Removed #{count} repositories."
- end
- end
-
-
- class Discover
- def initialize(base_command)
- @base_command = base_command
- @list = false
- @prompt = true
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} discover URI [URI [URI]...]"
- o.define_head "Discover repositories referenced on a page."
- o.separator ""
- o.separator "Options:"
- o.separator ""
- o.on( "-l", "--list",
- "List but don't prompt or add discovered repositories.") { |list| @list, @prompt = list, !@list }
- o.on( "-n", "--no-prompt",
- "Add all new repositories without prompting.") { |v| @prompt = !v }
- end
- end
-
- def parse!(args)
- options.parse!(args)
- args = ['http://wiki.rubyonrails.org/rails/pages/Plugins'] if args.empty?
- args.each do |uri|
- scrape(uri) do |repo_uri|
- catch(:next_uri) do
- if @prompt
- begin
- $stdout.print "Add #{repo_uri}? [Y/n] "
- throw :next_uri if $stdin.gets !~ /^y?$/i
- rescue Interrupt
- $stdout.puts
- exit 1
- end
- elsif @list
- puts repo_uri
- throw :next_uri
- end
- Repositories.instance.add(repo_uri)
- puts "discovered: #{repo_uri}" if $verbose or !@prompt
- end
- end
- end
- Repositories.instance.save
- end
-
- def scrape(uri)
- require 'open-uri'
- puts "Scraping #{uri}" if $verbose
- dupes = []
- content = open(uri).each do |line|
- begin
- if line =~ /<a[^>]*href=['"]([^'"]*)['"]/ || line =~ /(svn:\/\/[^<|\n]*)/
- uri = $1
- if uri =~ /^\w+:\/\// && uri =~ /\/plugins\// && uri !~ /\/browser\// && uri !~ /^http:\/\/wiki\.rubyonrails/ && uri !~ /http:\/\/instiki/
- uri = extract_repository_uri(uri)
- yield uri unless dupes.include?(uri) || Repositories.instance.exist?(uri)
- dupes << uri
- end
- end
- rescue
- puts "Problems scraping '#{uri}': #{$!.to_s}"
- end
- end
- end
-
- def extract_repository_uri(uri)
- uri.match(/(svn|https?):.*\/plugins\//i)[0]
- end
- end
-
class Install
def initialize(base_command)
@base_command = base_command
@@ -816,41 +426,6 @@ module Commands
end
end
- class Update
- def initialize(base_command)
- @base_command = base_command
- end
-
- def options
- OptionParser.new do |o|
- o.set_summary_indent(' ')
- o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
- o.on( "-r REVISION", "--revision REVISION",
- "Checks out the given revision from subversion.",
- "Ignored if subversion is not used.") { |v| @revision = v }
- o.define_head "Update plugins."
- end
- end
-
- def parse!(args)
- options.parse!(args)
- root = @base_command.environment.root
- cd root
- args = Dir["vendor/plugins/*"].map do |f|
- File.directory?("#{f}/.svn") ? File.basename(f) : nil
- end.compact if args.empty?
- cd "vendor/plugins"
- args.each do |name|
- if File.directory?(name)
- puts "Updating plugin: #{name}"
- system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}")
- else
- puts "Plugin doesn't exist: #{name}"
- end
- end
- end
- end
-
class Remove
def initialize(base_command)
@base_command = base_command
diff --git a/railties/lib/commands/server.rb b/railties/lib/commands/server.rb
index 43b18004c0..ebe34a42cd 100644
--- a/railties/lib/commands/server.rb
+++ b/railties/lib/commands/server.rb
@@ -17,7 +17,8 @@ options = {
:environment => (ENV['RAILS_ENV'] || "development").dup,
:config => RAILS_ROOT + "/config.ru",
:detach => false,
- :debugger => false
+ :debugger => false,
+ :path => nil
}
ARGV.clone.options do |opts|
@@ -32,6 +33,7 @@ ARGV.clone.options do |opts|
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |v| options[:environment] = v }
+ opts.on("-P", "--path=/path", String, "Runs Rails app mounted at a specific path.", "Default: /") { |v| options[:path] = v }
opts.separator ""
@@ -50,7 +52,7 @@ unless server
end
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
-puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}"
+puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}#{options[:path]}"
%w(cache pids sessions sockets).each do |dir_to_make|
FileUtils.mkdir_p(File.join(RAILS_ROOT, 'tmp', dir_to_make))
@@ -83,11 +85,20 @@ else
inner_app = ActionController::Dispatcher.new
end
+if options[:path].nil?
+ map_path = "/"
+else
+ ActionController::Base.relative_url_root = options[:path]
+ map_path = options[:path]
+end
+
app = Rack::Builder.new {
use Rails::Rack::LogTailer unless options[:detach]
- use Rails::Rack::Static
use Rails::Rack::Debugger if options[:debugger]
- run inner_app
+ map map_path do
+ use Rails::Rack::Static
+ run inner_app
+ end
}.to_app
puts "=> Call with -d to detach"
diff --git a/railties/lib/console_app.rb b/railties/lib/console_app.rb
index 96bf3117c8..d7d01d703f 100644
--- a/railties/lib/console_app.rb
+++ b/railties/lib/console_app.rb
@@ -24,8 +24,7 @@ end
#reloads the environment
def reload!
puts "Reloading..."
- dispatcher = ActionController::Dispatcher.new($stdout)
- dispatcher.cleanup_application
- dispatcher.reload_application
+ Dispatcher.cleanup_application
+ Dispatcher.reload_application
true
end
diff --git a/railties/lib/fcgi_handler.rb b/railties/lib/fcgi_handler.rb
index 1256ef2286..0cd2dc51c6 100644
--- a/railties/lib/fcgi_handler.rb
+++ b/railties/lib/fcgi_handler.rb
@@ -38,6 +38,8 @@ class RailsFCGIHandler
# Safely install signal handlers.
install_signal_handlers
+ @app = Dispatcher.new
+
# Start error timestamp at 11 seconds ago.
@last_error_on = Time.now - 11
end
@@ -69,36 +71,36 @@ class RailsFCGIHandler
protected
def process_each_request(provider)
- cgi = nil
+ request = nil
catch :exit do
- provider.each_cgi do |cgi|
- process_request(cgi)
+ provider.each do |request|
+ process_request(request)
case when_ready
when :reload
reload!
when :restart
- close_connection(cgi)
+ close_connection(request)
restart!
when :exit
- close_connection(cgi)
+ close_connection(request)
throw :exit
end
end
end
rescue SignalException => signal
raise unless signal.message == 'SIGUSR1'
- close_connection(cgi)
+ close_connection(request)
end
- def process_request(cgi)
+ def process_request(request)
@processing, @when_ready = true, nil
gc_countdown
with_signal_handler 'USR1' do
begin
- ::Rack::Handler::FastCGI.serve(cgi, Dispatcher.new)
+ ::Rack::Handler::FastCGI.serve(request, @app)
rescue SignalException, SystemExit
raise
rescue Exception => error
@@ -231,7 +233,7 @@ class RailsFCGIHandler
end
end
- def close_connection(cgi)
- cgi.instance_variable_get("@request").finish if cgi
+ def close_connection(request)
+ request.finish if request
end
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index da064c86aa..8eb4212737 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -132,10 +132,10 @@ module Rails
add_gem_load_paths
require_frameworks
- preload_frameworks
set_autoload_paths
add_plugin_load_paths
load_environment
+ preload_frameworks
initialize_encoding
initialize_database
@@ -167,11 +167,18 @@ module Rails
load_gems
check_gem_dependencies
+ # bail out if gems are missing - note that check_gem_dependencies will have
+ # already called abort() unless $gems_rake_task is set
+ return unless gems_dependencies_loaded
+
load_application_initializers
# the framework is now fully initialized
after_initialize
+ # Setup database middleware after initializers have run
+ initialize_database_middleware
+
# Prepare dispatcher callbacks and run 'prepare' callbacks
prepare_dispatcher
@@ -270,7 +277,7 @@ module Rails
configuration.frameworks.each do |framework|
# String#classify and #constantize aren't available yet.
toplevel = Object.const_get(framework.to_s.gsub(/(?:^|_)(.)/) { $1.upcase })
- toplevel.load_all!
+ toplevel.load_all! if toplevel.respond_to?(:load_all!)
end
end
end
@@ -294,7 +301,9 @@ module Rails
end
def load_gems
- @configuration.gems.each { |gem| gem.load }
+ unless $gems_build_rake_task
+ @configuration.gems.each { |gem| gem.load }
+ end
end
def check_gem_dependencies
@@ -302,7 +311,7 @@ module Rails
if unloaded_gems.size > 0
@gems_dependencies_loaded = false
# don't print if the gems rake tasks are being run
- unless $rails_rake_task
+ unless $gems_rake_task
abort <<-end_error
Missing these required gems:
#{unloaded_gems.map { |gem| "#{gem.name} #{gem.requirement}" } * "\n "}
@@ -409,7 +418,18 @@ Run `rake gems:install` to install the missing gems.
if configuration.frameworks.include?(:active_record)
ActiveRecord::Base.configurations = configuration.database_configuration
ActiveRecord::Base.establish_connection
- configuration.middleware.use ActiveRecord::QueryCache
+ end
+ end
+
+ def initialize_database_middleware
+ if configuration.frameworks.include?(:active_record)
+ if ActionController::Base.session_store == ActiveRecord::SessionStore
+ configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement
+ configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache
+ else
+ configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement
+ configuration.middleware.use ActiveRecord::QueryCache
+ end
end
end
@@ -481,9 +501,9 @@ Run `rake gems:install` to install the missing gems.
# set to use Configuration#view_path.
def initialize_framework_views
if configuration.frameworks.include?(:action_view)
- view_path = ActionView::Template::Path.new(configuration.view_path)
- ActionMailer::Base.template_root ||= view_path if configuration.frameworks.include?(:action_mailer)
- ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.empty?
+ view_path = ActionView::PathSet.type_cast(configuration.view_path)
+ ActionMailer::Base.template_root = view_path if configuration.frameworks.include?(:action_mailer) && ActionMailer::Base.view_paths.blank?
+ ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.blank?
end
end
@@ -495,7 +515,7 @@ Run `rake gems:install` to install the missing gems.
ActionController::Routing.controller_paths += configuration.controller_paths
ActionController::Routing::Routes.add_configuration_file(configuration.routes_configuration_file)
- ActionController::Routing::Routes.reload
+ ActionController::Routing::Routes.reload!
end
# Sets the dependency loading mechanism based on the value of
@@ -544,6 +564,9 @@ Run `rake gems:install` to install the missing gems.
end
def initialize_metal
+ Rails::Rack::Metal.requested_metals = configuration.metals
+ Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths
+
configuration.middleware.insert_before(
:"ActionController::RewindableInput",
Rails::Rack::Metal, :if => Rails::Rack::Metal.metals.any?)
@@ -586,7 +609,7 @@ Run `rake gems:install` to install the missing gems.
return unless configuration.frameworks.include?(:action_controller)
require 'dispatcher' unless defined?(::Dispatcher)
Dispatcher.define_dispatcher_callbacks(configuration.cache_classes)
- Dispatcher.new(Rails.logger).send :run_callbacks, :prepare_dispatch
+ Dispatcher.run_prepare_callbacks
end
def disable_dependency_loading
@@ -698,6 +721,11 @@ Run `rake gems:install` to install the missing gems.
@plugins = plugins.nil? ? nil : plugins.map { |p| p.to_sym }
end
+ # The list of metals to load. If this is set to <tt>nil</tt>, all metals will
+ # be loaded in alphabetical order. If this is set to <tt>[]</tt>, no metals will
+ # be loaded. Otherwise metals will be loaded in the order specified
+ attr_accessor :metals
+
# The path to the root of the plugins directory. By default, it is in
# <tt>vendor/plugins</tt>.
attr_accessor :plugin_paths
@@ -837,7 +865,8 @@ Run `rake gems:install` to install the missing gems.
# Enable threaded mode. Allows concurrent requests to controller actions and
# multiple database connections. Also disables automatic dependency loading
- # after boot
+ # after boot, and disables reloading code on every request, as these are
+ # fundamentally incompatible with thread safety.
def threadsafe!
self.preload_frameworks = true
self.cache_classes = true
diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb
index e1b422716d..923ed8b31d 100644
--- a/railties/lib/rails/backtrace_cleaner.rb
+++ b/railties/lib/rails/backtrace_cleaner.rb
@@ -2,15 +2,15 @@ module Rails
class BacktraceCleaner < ActiveSupport::BacktraceCleaner
ERB_METHOD_SIG = /:in `_run_erb_.*/
- VENDOR_DIRS = %w( vendor/gems vendor/rails )
+ RAILS_GEMS = %w( actionpack activerecord actionmailer activesupport activeresource rails )
+
+ VENDOR_DIRS = %w( vendor/rails )
SERVER_DIRS = %w( lib/mongrel bin/mongrel
lib/passenger bin/passenger-spawn-server
lib/rack )
RAILS_NOISE = %w( script/server )
RUBY_NOISE = %w( rubygems/custom_require benchmark.rb )
- GEMS_DIR = Gem.default_dir
-
ALL_NOISE = VENDOR_DIRS + SERVER_DIRS + RAILS_NOISE + RUBY_NOISE
def initialize
@@ -18,10 +18,25 @@ module Rails
add_filter { |line| line.sub("#{RAILS_ROOT}/", '') }
add_filter { |line| line.sub(ERB_METHOD_SIG, '') }
add_filter { |line| line.sub('./', '/') } # for tests
- add_filter { |line| line.sub(/(#{GEMS_DIR})\/gems\/([a-z]+)-([0-9.]+)\/(.*)/, '\2 (\3) \4')} # http://gist.github.com/30430
+
+ add_gem_filters
+
add_silencer { |line| ALL_NOISE.any? { |dir| line.include?(dir) } }
+ add_silencer { |line| RAILS_GEMS.any? { |gem| line =~ /^#{gem} / } }
add_silencer { |line| line =~ %r(vendor/plugins/[^\/]+/lib) }
end
+
+
+ private
+ def add_gem_filters
+ Gem.path.each do |path|
+ # http://gist.github.com/30430
+ add_filter { |line| line.sub(/(#{path})\/gems\/([a-z]+)-([0-9.]+)\/(.*)/, '\2 (\3) \4')}
+ end
+
+ vendor_gems_path = Rails::GemDependency.unpacked_path.sub("#{RAILS_ROOT}/",'')
+ add_filter { |line| line.sub(/(#{vendor_gems_path})\/([a-z]+)-([0-9.]+)\/(.*)/, '\2 (\3) [v] \4')}
+ end
end
# For installing the BacktraceCleaner in the test/unit
diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb
index 5a07841be8..3062a77104 100644
--- a/railties/lib/rails/gem_dependency.rb
+++ b/railties/lib/rails/gem_dependency.rb
@@ -7,8 +7,8 @@ module Gem
end
module Rails
- class GemDependency
- attr_accessor :lib, :source
+ class GemDependency < Gem::Dependency
+ attr_accessor :lib, :source, :dep
def self.unpacked_path
@unpacked_path ||= File.join(RAILS_ROOT, 'vendor', 'gems')
@@ -29,18 +29,6 @@ module Rails
end
end
- def framework_gem?
- @@framework_gems.has_key?(name)
- end
-
- def vendor_rails?
- Gem.loaded_specs.has_key?(name) && Gem.loaded_specs[name].loaded_from.empty?
- end
-
- def vendor_gem?
- Gem.loaded_specs.has_key?(name) && Gem.loaded_specs[name].loaded_from.include?(self.class.unpacked_path)
- end
-
def initialize(name, options = {})
require 'rubygems' unless Object.const_defined?(:Gem)
@@ -52,10 +40,11 @@ module Rails
req = Gem::Requirement.default
end
- @dep = Gem::Dependency.new(name, req)
@lib = options[:lib]
@source = options[:source]
@loaded = @frozen = @load_paths_added = false
+
+ super(name, req)
end
def add_load_paths
@@ -65,7 +54,7 @@ module Rails
@load_paths_added = @loaded = @frozen = true
return
end
- gem @dep
+ gem self
@spec = Gem.loaded_specs[name]
@frozen = @spec.loaded_from.include?(self.class.unpacked_path) if @spec
@load_paths_added = true
@@ -74,44 +63,67 @@ module Rails
def dependencies
return [] if framework_gem?
- return [] if specification.nil?
- all_dependencies = specification.dependencies.map do |dependency|
+ return [] unless installed?
+ specification.dependencies.reject do |dependency|
+ dependency.type == :development
+ end.map do |dependency|
GemDependency.new(dependency.name, :requirement => dependency.version_requirements)
end
- all_dependencies += all_dependencies.map(&:dependencies).flatten
- all_dependencies.uniq
end
- def gem_dir(base_directory)
- File.join(base_directory, specification.full_name)
- end
-
- def spec_filename(base_directory)
- File.join(gem_dir(base_directory), '.specification')
+ def specification
+ # code repeated from Gem.activate. Find a matching spec, or the currently loaded version.
+ # error out if loaded version and requested version are incompatible.
+ @spec ||= begin
+ matches = Gem.source_index.search(self)
+ matches << @@framework_gems[name] if framework_gem?
+ if Gem.loaded_specs[name] then
+ # This gem is already loaded. If the currently loaded gem is not in the
+ # list of candidate gems, then we have a version conflict.
+ existing_spec = Gem.loaded_specs[name]
+ unless matches.any? { |spec| spec.version == existing_spec.version } then
+ raise Gem::Exception,
+ "can't activate #{@dep}, already activated #{existing_spec.full_name}"
+ end
+ # we're stuck with it, so change to match
+ version_requirements = Gem::Requirement.create("=#{existing_spec.version}")
+ existing_spec
+ else
+ # new load
+ matches.last
+ end
+ end
end
- def load
- return if @loaded || @load_paths_added == false
- require(@lib || name) unless @lib == false
- @loaded = true
- rescue LoadError
- puts $!.to_s
- $!.backtrace.each { |b| puts b }
+ def requirement
+ r = version_requirements
+ (r == Gem::Requirement.default) ? nil : r
end
- def name
- @dep.name.to_s
+ def built?
+ # TODO: If Rubygems ever gives us a way to detect this, we should use it
+ false
end
- def requirement
- r = @dep.version_requirements
- (r == Gem::Requirement.default) ? nil : r
+ def framework_gem?
+ @@framework_gems.has_key?(name)
end
def frozen?
@frozen ||= vendor_rails? || vendor_gem?
end
+ def installed?
+ Gem.loaded_specs.keys.include?(name)
+ end
+
+ def load_paths_added?
+ # always try to add load paths - even if a gem is loaded, it may not
+ # be a compatible version (ie random_gem 0.4 is loaded and a later spec
+ # needs >= 0.5 - gem 'random_gem' will catch this and error out)
+ @load_paths_added
+ end
+
def loaded?
@loaded ||= begin
if vendor_rails?
@@ -135,46 +147,49 @@ module Rails
end
end
- def load_paths_added?
- # always try to add load paths - even if a gem is loaded, it may not
- # be a compatible version (ie random_gem 0.4 is loaded and a later spec
- # needs >= 0.5 - gem 'random_gem' will catch this and error out)
- @load_paths_added
+ def vendor_rails?
+ Gem.loaded_specs.has_key?(name) && Gem.loaded_specs[name].loaded_from.empty?
end
- def install
- cmd = "#{gem_command} #{install_command.join(' ')}"
- puts cmd
- puts %x(#{cmd})
+ def vendor_gem?
+ specification && File.exists?(unpacked_gem_directory)
end
- def unpack_to(directory)
- FileUtils.mkdir_p directory
- Dir.chdir directory do
- Gem::GemRunner.new.run(unpack_command)
+ def build
+ require 'rails/gem_builder'
+ unless built?
+ return unless File.exists?(unpacked_specification_filename)
+ spec = YAML::load_file(unpacked_specification_filename)
+ Rails::GemBuilder.new(spec, unpacked_gem_directory).build_extensions
+ puts "Built gem: '#{unpacked_gem_directory}'"
end
-
- # Gem.activate changes the spec - get the original
- real_spec = Gem::Specification.load(specification.loaded_from)
- write_spec(directory, real_spec)
-
+ dependencies.each { |dep| dep.build }
end
- def write_spec(directory, spec)
- # copy the gem's specification into GEMDIR/.specification so that
- # we can access information about the gem on deployment systems
- # without having the gem installed
- File.open(spec_filename(directory), 'w') do |file|
- file.puts spec.to_yaml
+ def install
+ unless installed?
+ cmd = "#{gem_command} #{install_command.join(' ')}"
+ puts cmd
+ puts %x(#{cmd})
end
end
- def refresh_spec(directory)
+ def load
+ return if @loaded || @load_paths_added == false
+ require(@lib || name) unless @lib == false
+ @loaded = true
+ rescue LoadError
+ puts $!.to_s
+ $!.backtrace.each { |b| puts b }
+ end
+
+ def refresh
+ Rails::VendorGemSourceIndex.silence_spec_warnings = true
real_gems = Gem.source_index.installed_source_index
exact_dep = Gem::Dependency.new(name, "= #{specification.version}")
matches = real_gems.search(exact_dep)
installed_spec = matches.first
- if File.exist?(File.dirname(spec_filename(directory)))
+ if frozen?
if installed_spec
# we have a real copy
# get a fresh spec - matches should only have one element
@@ -182,11 +197,11 @@ module Rails
# spec is the same as the copy from real_gems - Gem.activate changes
# some of the fields
real_spec = Gem::Specification.load(matches.first.loaded_from)
- write_spec(directory, real_spec)
+ write_specification(real_spec)
puts "Reloaded specification for #{name} from installed gems."
else
# the gem isn't installed locally - write out our current specs
- write_spec(directory, specification)
+ write_specification(specification)
puts "Gem #{name} not loaded locally - writing out current spec."
end
else
@@ -198,42 +213,44 @@ module Rails
end
end
- def ==(other)
- self.name == other.name && self.requirement == other.requirement
+ def unpack(options={})
+ unless frozen? || framework_gem?
+ FileUtils.mkdir_p unpack_base
+ Dir.chdir unpack_base do
+ Gem::GemRunner.new.run(unpack_command)
+ end
+ # Gem.activate changes the spec - get the original
+ real_spec = Gem::Specification.load(specification.loaded_from)
+ write_specification(real_spec)
+ end
+ dependencies.each { |dep| dep.unpack } if options[:recursive]
end
- alias_method :"eql?", :"=="
- def hash
- @dep.hash
+ def write_specification(spec)
+ # copy the gem's specification into GEMDIR/.specification so that
+ # we can access information about the gem on deployment systems
+ # without having the gem installed
+ File.open(unpacked_specification_filename, 'w') do |file|
+ file.puts spec.to_yaml
+ end
end
- def specification
- # code repeated from Gem.activate. Find a matching spec, or the currently loaded version.
- # error out if loaded version and requested version are incompatible.
- @spec ||= begin
- matches = Gem.source_index.search(@dep)
- matches << @@framework_gems[name] if framework_gem?
- if Gem.loaded_specs[name] then
- # This gem is already loaded. If the currently loaded gem is not in the
- # list of candidate gems, then we have a version conflict.
- existing_spec = Gem.loaded_specs[name]
- unless matches.any? { |spec| spec.version == existing_spec.version } then
- raise Gem::Exception,
- "can't activate #{@dep}, already activated #{existing_spec.full_name}"
- end
- # we're stuck with it, so change to match
- @dep.version_requirements = Gem::Requirement.create("=#{existing_spec.version}")
- existing_spec
- else
- # new load
- matches.last
- end
- end
+ def ==(other)
+ self.name == other.name && self.requirement == other.requirement
end
+ alias_method :"eql?", :"=="
private
+
def gem_command
- RUBY_PLATFORM =~ /win32/ ? 'gem.bat' : 'gem'
+ case RUBY_PLATFORM
+ when /win32/
+ 'gem.bat'
+ when /java/
+ 'jruby -S gem'
+ else
+ 'gem'
+ end
end
def install_command
@@ -248,5 +265,18 @@ module Rails
cmd << "--version" << "= "+specification.version.to_s if requirement
cmd
end
+
+ def unpack_base
+ Rails::GemDependency.unpacked_path
+ end
+
+ def unpacked_gem_directory
+ File.join(unpack_base, specification.full_name)
+ end
+
+ def unpacked_specification_filename
+ File.join(unpacked_gem_directory, '.specification')
+ end
+
end
end
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 4901abe808..80deb73bbb 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -80,6 +80,10 @@ module Rails
File.join(directory, 'app', 'controllers')
end
+ def metal_path
+ File.join(directory, 'app', 'metal')
+ end
+
def routing_file
File.join(directory, 'config', 'routes.rb')
end
@@ -100,7 +104,7 @@ module Rails
def app_paths
- [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path ]
+ [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ]
end
def lib_path
@@ -160,4 +164,4 @@ module Rails
File.join(directory, 'rails', 'init.rb')
end
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/plugin/loader.rb b/railties/lib/rails/plugin/loader.rb
index be81bdf4fa..66e01d70da 100644
--- a/railties/lib/rails/plugin/loader.rb
+++ b/railties/lib/rails/plugin/loader.rb
@@ -16,7 +16,7 @@ module Rails
def initialize(initializer)
@initializer = initializer
end
-
+
# Returns the plugins to be loaded, in the order they should be loaded.
def plugins
@plugins ||= all_plugins.select { |plugin| should_load?(plugin) }.sort { |p1, p2| order_plugins(p1, p2) }
@@ -32,9 +32,9 @@ module Rails
@all_plugins ||= locate_plugins
@all_plugins
end
-
+
def load_plugins
- plugins.each do |plugin|
+ plugins.each do |plugin|
plugin.load(initializer)
register_plugin_as_loaded(plugin)
end
@@ -43,12 +43,12 @@ module Rails
ensure_all_registered_plugins_are_loaded!
end
-
+
# Adds the load paths for every plugin into the $LOAD_PATH. Plugin load paths are
# added *after* the application's <tt>lib</tt> directory, to ensure that an application
# can always override code within a plugin.
#
- # Plugin load paths are also added to Dependencies.load_paths, and Dependencies.load_once_paths.
+ # Plugin load paths are also added to Dependencies.load_paths, and Dependencies.load_once_paths.
def add_plugin_load_paths
plugins.each do |plugin|
plugin.load_paths.each do |path|
@@ -56,7 +56,7 @@ module Rails
ActiveSupport::Dependencies.load_paths << path
- unless Rails.configuration.reload_plugins?
+ unless configuration.reload_plugins?
ActiveSupport::Dependencies.load_once_paths << path
end
end
@@ -64,8 +64,11 @@ module Rails
$LOAD_PATH.uniq!
end
-
-
+
+ def engine_metal_paths
+ engines.collect(&:metal_path)
+ end
+
protected
def configure_engines
if engines.any?
@@ -74,20 +77,22 @@ module Rails
add_engine_view_paths
end
end
-
+
def add_engine_routing_configurations
engines.select(&:routed?).collect(&:routing_file).each do |routing_file|
ActionController::Routing::Routes.add_configuration_file(routing_file)
end
end
-
+
def add_engine_controller_paths
ActionController::Routing.controller_paths += engines.collect(&:controller_path)
end
-
+
def add_engine_view_paths
# reverse it such that the last engine can overwrite view paths from the first, like with routes
- ActionController::Base.view_paths += ActionView::PathSet.new(engines.collect(&:view_path).reverse)
+ paths = ActionView::PathSet.new(engines.collect(&:view_path).reverse)
+ ActionController::Base.view_paths.concat(paths)
+ ActionMailer::Base.view_paths.concat(paths) if configuration.frameworks.include?(:action_mailer)
end
# The locate_plugins method uses each class in config.plugin_locators to
@@ -106,7 +111,7 @@ module Rails
def configuration
initializer.configuration
end
-
+
def should_load?(plugin)
# uses Plugin#name and Plugin#valid?
enabled?(plugin) && plugin.valid?
@@ -120,21 +125,21 @@ module Rails
plugin_a <=> plugin_b
else
effective_order_of(plugin_a) <=> effective_order_of(plugin_b)
- end
+ end
end
end
-
+
def effective_order_of(plugin)
if explicitly_enabled?(plugin)
- registered_plugin_names.index(plugin.name)
+ registered_plugin_names.index(plugin.name)
else
registered_plugin_names.index('all')
- end
+ end
end
def application_lib_index
$LOAD_PATH.index(File.join(RAILS_ROOT, 'lib')) || 0
- end
+ end
def enabled?(plugin)
!explicit_plugin_loading_order? || registered?(plugin)
@@ -155,32 +160,32 @@ module Rails
def explicitly_registered?(plugin)
explicit_plugin_loading_order? && registered_plugin_names.include?(plugin.name)
end
-
+
def registered_plugins_names_plugin?(plugin)
registered_plugin_names.include?(plugin.name) || registered_plugin_names.include?('all')
end
-
+
# The plugins that have been explicitly listed with config.plugins. If this list is nil
- # then it means the client does not care which plugins or in what order they are loaded,
+ # then it means the client does not care which plugins or in what order they are loaded,
# so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
# non empty, we load the named plugins in the order specified.
def registered_plugin_names
configuration.plugins ? configuration.plugins.map(&:to_s) : nil
end
-
+
def loaded?(plugin_name)
initializer.loaded_plugins.detect { |plugin| plugin.name == plugin_name.to_s }
end
-
+
def ensure_all_registered_plugins_are_loaded!
if explicit_plugin_loading_order?
if configuration.plugins.detect {|plugin| plugin != :all && !loaded?(plugin) }
- missing_plugins = configuration.plugins - (plugins + [:all])
- raise LoadError, "Could not locate the following plugins: #{missing_plugins.to_sentence}"
+ missing_plugins = configuration.plugins - (plugins.map{|p| p.name.to_sym} + [:all])
+ raise LoadError, "Could not locate the following plugins: #{missing_plugins.to_sentence(:locale => :en)}"
end
end
end
-
+
end
end
-end \ No newline at end of file
+end
diff --git a/railties/lib/rails/rack/metal.rb b/railties/lib/rails/rack/metal.rb
index b185227234..adc43da864 100644
--- a/railties/lib/rails/rack/metal.rb
+++ b/railties/lib/rails/rack/metal.rb
@@ -6,15 +6,30 @@ module Rails
NotFoundResponse = [404, {}, []].freeze
NotFound = lambda { NotFoundResponse }
+ cattr_accessor :metal_paths
+ self.metal_paths = ["#{Rails.root}/app/metal"]
+ cattr_accessor :requested_metals
+
def self.metals
- base = "#{Rails.root}/app/metal"
- matcher = /\A#{Regexp.escape(base)}\/(.*)\.rb\Z/
+ matcher = /#{Regexp.escape('/app/metal/')}(.*)\.rb\Z/
+ metal_glob = metal_paths.map{ |base| "#{base}/**/*.rb" }
+ all_metals = {}
- Dir["#{base}/**/*.rb"].sort.map do |file|
- file.sub!(matcher, '\1')
- require file
- file.classify.constantize
+ metal_glob.each do |glob|
+ Dir[glob].sort.map do |file|
+ file = file.match(matcher)[1]
+ all_metals[file.camelize] = file
+ end
end
+
+ load_list = requested_metals || all_metals.keys
+
+ load_list.map do |requested_metal|
+ if metal = all_metals[requested_metal]
+ require metal
+ requested_metal.constantize
+ end
+ end.compact
end
def initialize(app)
diff --git a/railties/lib/rails/rack/static.rb b/railties/lib/rails/rack/static.rb
index ef4e2642e2..f07c6beb5e 100644
--- a/railties/lib/rails/rack/static.rb
+++ b/railties/lib/rails/rack/static.rb
@@ -13,14 +13,18 @@ module Rails
def call(env)
path = env['PATH_INFO'].chomp('/')
method = env['REQUEST_METHOD']
- cached_path = (path.empty? ? 'index' : path) + ::ActionController::Base.page_cache_extension
if FILE_METHODS.include?(method)
if file_exist?(path)
return @file_server.call(env)
- elsif file_exist?(cached_path)
- env['PATH_INFO'] = cached_path
- return @file_server.call(env)
+ else
+ cached_path = directory_exist?(path) ? "#{path}/index" : path
+ cached_path += ::ActionController::Base.page_cache_extension
+
+ if file_exist?(cached_path)
+ env['PATH_INFO'] = cached_path
+ return @file_server.call(env)
+ end
end
end
@@ -32,6 +36,11 @@ module Rails
full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path))
File.file?(full_path) && File.readable?(full_path)
end
+
+ def directory_exist?(path)
+ full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path))
+ File.directory?(full_path) && File.readable?(full_path)
+ end
end
end
end
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index 9bb4b2a96d..99c7516a65 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -2,7 +2,7 @@ module Rails
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 0
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
diff --git a/railties/lib/rails_generator/commands.rb b/railties/lib/rails_generator/commands.rb
index 299044c3d7..b684dc92be 100644
--- a/railties/lib/rails_generator/commands.rb
+++ b/railties/lib/rails_generator/commands.rb
@@ -182,15 +182,19 @@ HELP
nesting = class_name.split('::')
name = nesting.pop
+ # Hack to limit const_defined? to non-inherited on 1.9.
+ extra = []
+ extra << false unless Object.method(:const_defined?).arity == 1
+
# Extract the last Module in the nesting.
last = nesting.inject(Object) { |last, nest|
- break unless last.const_defined?(nest)
+ break unless last.const_defined?(nest, *extra)
last.const_get(nest)
}
# If the last Module exists, check whether the given
# class exists and raise a collision if so.
- if last and last.const_defined?(name.camelize)
+ if last and last.const_defined?(name.camelize, *extra)
raise_class_collision(class_name)
end
end
diff --git a/railties/lib/rails_generator/generators/applications/app/template_runner.rb b/railties/lib/rails_generator/generators/applications/app/template_runner.rb
index 84e36ecc1b..3b49b1fa92 100644
--- a/railties/lib/rails_generator/generators/applications/app/template_runner.rb
+++ b/railties/lib/rails_generator/generators/applications/app/template_runner.rb
@@ -75,7 +75,7 @@ module Rails
end
elsif options[:git] || options[:svn]
in_root do
- run("script/plugin install #{options[:svn] || options[:git]}", false)
+ run_ruby_script("script/plugin install #{options[:svn] || options[:git]}", false)
end
else
log "! no git or svn provided for #{name}. skipping..."
@@ -85,26 +85,35 @@ module Rails
# Adds an entry into config/environment.rb for the supplied gem :
def gem(name, options = {})
log 'gem', name
+ env = options.delete(:env)
gems_code = "config.gem '#{name}'"
if options.any?
- opts = options.inject([]) {|result, h| result << [":#{h[0]} => '#{h[1]}'"] }.sort.join(", ")
+ opts = options.inject([]) {|result, h| result << [":#{h[0]} => #{h[1].inspect.gsub('"',"'")}"] }.sort.join(", ")
gems_code << ", #{opts}"
end
- environment gems_code
+ environment gems_code, :env => env
end
# Adds a line inside the Initializer block for config/environment.rb. Used by #gem
- def environment(data = nil, &block)
+ # If options :env is specified, the line is appended to the corresponding
+ # file in config/environments/#{env}.rb
+ def environment(data = nil, options = {}, &block)
sentinel = 'Rails::Initializer.run do |config|'
data = block.call if !data && block_given?
in_root do
- gsub_file 'config/environment.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
- "#{match}\n " << data
+ if options[:env].nil?
+ gsub_file 'config/environment.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
+ "#{match}\n " << data
+ end
+ else
+ Array.wrap(options[:env]).each do|env|
+ append_file "config/environments/#{env}.rb", "\n#{data}"
+ end
end
end
end
@@ -220,7 +229,7 @@ module Rails
log 'generating', what
argument = args.map(&:to_s).flatten.join(" ")
- in_root { run("script/generate #{what} #{argument}", false) }
+ in_root { run_ruby_script("script/generate #{what} #{argument}", false) }
end
# Executes a command
@@ -236,6 +245,12 @@ module Rails
`#{command}`
end
+ # Executes a ruby script (taking into account WIN32 platform quirks)
+ def run_ruby_script(command, log_action = true)
+ ruby_command = RUBY_PLATFORM=~ /win32/ ? 'ruby ' : ''
+ run("#{ruby_command}#{command}", log_action)
+ end
+
# Runs the supplied rake task
#
# ==== Example
@@ -301,7 +316,7 @@ module Rails
#
def ask(string)
log '', string
- gets.strip
+ STDIN.gets.strip
end
# Do something in the root of the Rails application or
@@ -350,6 +365,17 @@ module Rails
File.open(path, 'wb') { |file| file.write(content) }
end
+ # Append text to a file
+ #
+ # ==== Example
+ #
+ # append_file 'config/environments/test.rb', 'config.gem "rspec"'
+ #
+ def append_file(relative_destination, data)
+ path = destination_path(relative_destination)
+ File.open(path, 'ab') { |file| file.write(data) }
+ end
+
def destination_path(relative_destination)
File.join(root, relative_destination)
end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
index cbfd88f3bd..4d190b9362 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
@@ -2,7 +2,7 @@ class <%= controller_class_name %>Controller < ApplicationController
# GET /<%= table_name %>
# GET /<%= table_name %>.xml
def index
- @<%= table_name %> = <%= class_name %>.find(:all)
+ @<%= table_name %> = <%= class_name %>.all
respond_to do |format|
format.html # index.html.erb
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
index 2d9d635944..cd2fc578bf 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
@@ -21,23 +21,23 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase
end
test "should show <%= file_name %>" do
- get :show, :id => <%= table_name %>(:one).id
+ get :show, :id => <%= table_name %>(:one).to_param
assert_response :success
end
test "should get edit" do
- get :edit, :id => <%= table_name %>(:one).id
+ get :edit, :id => <%= table_name %>(:one).to_param
assert_response :success
end
test "should update <%= file_name %>" do
- put :update, :id => <%= table_name %>(:one).id, :<%= file_name %> => { }
+ put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
end
test "should destroy <%= file_name %>" do
assert_difference('<%= class_name %>.count', -1) do
- delete :destroy, :id => <%= table_name %>(:one).id
+ delete :destroy, :id => <%= table_name %>(:one).to_param
end
assert_redirected_to <%= table_name %>_path
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb
index 5c1f304232..ebc97f8130 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb
@@ -11,7 +11,7 @@
<p style="color: green"><%%= flash[:notice] %></p>
-<%%= yield %>
+<%%= yield %>
</body>
</html>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb
index e289975596..cca1d61c68 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb
@@ -10,9 +10,9 @@
</p>
<% end -%>
<p>
- <%%= f.submit "Update" %>
+ <%%= f.submit 'Update' %>
</p>
<%% end %>
<%%= link_to 'Show', @<%= singular_name %> %> |
-<%%= link_to 'Back', <%= plural_name %>_path %>
+<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb
index e89757e3e9..2e603d5b4a 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb
@@ -7,7 +7,7 @@
<% end -%>
</tr>
-<%% for <%= singular_name %> in @<%= plural_name %> %>
+<%% @<%= plural_name %>.each do |<%= singular_name %>| %>
<tr>
<% for attribute in attributes -%>
<td><%%=h <%= singular_name %>.<%= attribute.name %> %></td>
@@ -21,4 +21,4 @@
<br />
-<%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %>
+<%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %> \ No newline at end of file
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb
index c47e8117b4..96c89fc50e 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb
@@ -10,8 +10,8 @@
</p>
<% end -%>
<p>
- <%%= f.submit "Create" %>
+ <%%= f.submit 'Create' %>
</p>
<%% end %>
-<%%= link_to 'Back', <%= plural_name %>_path %>
+<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb
index 9b6b11b029..adecaf70c6 100644
--- a/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb
@@ -7,4 +7,4 @@
<% end -%>
<%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %> |
-<%%= link_to 'Back', <%= plural_name %>_path %>
+<%%= link_to 'Back', <%= plural_name %>_path %> \ No newline at end of file
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 68ffefae0b..9588fabb2d 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -250,6 +250,7 @@ namespace :db do
File.open(ENV['SCHEMA'] || "#{RAILS_ROOT}/db/schema.rb", "w") do |file|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
+ Rake::Task["db:schema:dump"].reenable
end
desc "Load a schema.rb file into the database"
diff --git a/railties/lib/tasks/documentation.rake b/railties/lib/tasks/documentation.rake
index 6caf69ccd3..8b41478a93 100644
--- a/railties/lib/tasks/documentation.rake
+++ b/railties/lib/tasks/documentation.rake
@@ -54,15 +54,8 @@ namespace :doc do
desc "Generate Rails guides"
task :guides do
- source = File.join(RAILTIES_PATH, "doc/guides")
- destination = File.join(RAILS_ROOT, "doc/guides")
- FileUtils.rm_r(destination) if File.directory?(destination)
- FileUtils.mkdir(destination)
-
- FileUtils.cp_r File.join(source, 'html/.'), File.join(destination)
- # Copy images and css files to html directory. These dirs are in .gitigore and shouldn't be source controlled.
- FileUtils.cp_r File.join(source, 'source/images'), File.join(destination)
- FileUtils.cp_r File.join(source, 'source/stylesheets'), File.join(destination, 'stylesheets')
+ require File.join(RAILTIES_PATH, "guides/rails_guides")
+ RailsGuides::Generator.new(File.join(RAILS_ROOT, "doc/guides")).generate
end
namespace :plugins do
diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake
index e6731ab78c..ed07bf2016 100644
--- a/railties/lib/tasks/gems.rake
+++ b/railties/lib/tasks/gems.rake
@@ -9,72 +9,57 @@ task :gems => 'gems:base' do
puts "R = Framework (loaded before rails starts)"
end
-def print_gem_status(gem, indent=1)
- code = gem.loaded? ? (gem.frozen? ? (gem.framework_gem? ? "R" : "F") : "I") : " "
- puts " "*(indent-1)+" - [#{code}] #{gem.name} #{gem.requirement.to_s}"
- gem.dependencies.each { |g| print_gem_status(g, indent+1)} if gem.loaded?
-end
-
namespace :gems do
task :base do
- $rails_rake_task = true
+ $gems_rake_task = true
+ require 'rubygems'
+ require 'rubygems/gem_runner'
Rake::Task[:environment].invoke
end
desc "Build any native extensions for unpacked gems"
task :build do
- $rails_rake_task = true
- require 'rails/gem_builder'
- Dir[File.join(Rails::GemDependency.unpacked_path, '*')].each do |gem_dir|
- spec_file = File.join(gem_dir, '.specification')
- next unless File.exists?(spec_file)
- specification = YAML::load_file(spec_file)
- next unless ENV['GEM'].blank? || ENV['GEM'] == specification.name
- Rails::GemBuilder.new(specification, gem_dir).build_extensions
- puts "Built gem: '#{gem_dir}'"
- end
+ $gems_build_rake_task = true
+ Rake::Task['gems:unpack'].invoke
+ current_gems.each &:build
end
- desc "Installs all required gems for this application."
+ desc "Installs all required gems."
task :install => :base do
- require 'rubygems'
- require 'rubygems/gem_runner'
- Rails.configuration.gems.each { |gem| gem.install unless gem.loaded? }
+ current_gems.each &:install
end
- desc "Unpacks the specified gem into vendor/gems."
- task :unpack => :base do
- require 'rubygems'
- require 'rubygems/gem_runner'
- Rails.configuration.gems.each do |gem|
- next unless !gem.frozen? && (ENV['GEM'].blank? || ENV['GEM'] == gem.name)
- gem.unpack_to(Rails::GemDependency.unpacked_path) if gem.loaded?
- end
+ desc "Unpacks all required gems into vendor/gems."
+ task :unpack => :install do
+ current_gems.each &:unpack
end
namespace :unpack do
- desc "Unpacks the specified gems and its dependencies into vendor/gems"
- task :dependencies => :unpack do
- require 'rubygems'
- require 'rubygems/gem_runner'
- Rails.configuration.gems.each do |gem|
- next unless ENV['GEM'].blank? || ENV['GEM'] == gem.name
- gem.dependencies.each do |dependency|
- next if dependency.frozen?
- dependency.unpack_to(Rails::GemDependency.unpacked_path)
- end
- end
+ desc "Unpacks all required gems and their dependencies into vendor/gems."
+ task :dependencies => :install do
+ current_gems.each { |gem| gem.unpack(:recursive => true) }
end
end
desc "Regenerate gem specifications in correct format."
task :refresh_specs => :base do
- require 'rubygems'
- require 'rubygems/gem_runner'
- Rails::VendorGemSourceIndex.silence_spec_warnings = true
- Rails.configuration.gems.each do |gem|
- next unless gem.frozen? && (ENV['GEM'].blank? || ENV['GEM'] == gem.name)
- gem.refresh_spec(Rails::GemDependency.unpacked_path) if gem.loaded?
- end
+ current_gems.each &:refresh
end
-end \ No newline at end of file
+end
+
+def current_gems
+ gems = Rails.configuration.gems
+ gems = gems.select { |gem| gem.name == ENV['GEM'] } unless ENV['GEM'].blank?
+ gems
+end
+
+def print_gem_status(gem, indent=1)
+ code = case
+ when gem.framework_gem? then 'R'
+ when gem.frozen? then 'F'
+ when gem.installed? then 'I'
+ else ' '
+ end
+ puts " "*(indent-1)+" - [#{code}] #{gem.name} #{gem.requirement.to_s}"
+ gem.dependencies.each { |g| print_gem_status(g, indent+1) }
+end
diff --git a/railties/lib/tasks/testing.rake b/railties/lib/tasks/testing.rake
index 4242458672..fd5e52a05b 100644
--- a/railties/lib/tasks/testing.rake
+++ b/railties/lib/tasks/testing.rake
@@ -48,7 +48,7 @@ task :test do
task
end
end.compact
- abort "Errors running #{errors.to_sentence}!" if errors.any?
+ abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any?
end
namespace :test do