aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails')
-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
7 files changed, 216 insertions, 138 deletions
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