aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/environments/boot.rb1
-rw-r--r--railties/lib/initializer.rb25
-rw-r--r--railties/lib/rails/plugin.rb20
-rw-r--r--railties/lib/rails/plugin/locator.rb21
5 files changed, 67 insertions, 2 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index ac17d7a0ad..818bbce1ac 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Added that gems can now be plugins if they include rails/init.rb #11444 [jbarnette]
+
* Added Plugin#about method to programmatically access the about.yml in a plugin #10979 [lazyatom]
plugin = Rails::Plugin.new(path_to_my_plugin)
diff --git a/railties/environments/boot.rb b/railties/environments/boot.rb
index fc8372309b..cd21fb9eab 100644
--- a/railties/environments/boot.rb
+++ b/railties/environments/boot.rb
@@ -43,6 +43,7 @@ module Rails
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
+ Rails::Initializer.run(:install_gem_spec_stubs)
end
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 32e6c5251b..c3ebffdf03 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -72,6 +72,7 @@ module Rails
Rails.configuration = configuration
check_ruby_version
+ install_gem_spec_stubs
set_load_path
require_frameworks
@@ -118,6 +119,26 @@ module Rails
require 'ruby_version_check'
end
+ # If Rails is vendored and RubyGems is available, install stub GemSpecs
+ # for Rails, ActiveSupport, ActiveRecord, ActionPack, ActionMailer, and
+ # ActiveResource. This allows Gem plugins to depend on Rails even when
+ # the Gem version of Rails shouldn't be loaded.
+ def install_gem_spec_stubs
+ if Rails.vendor_rails?
+ begin; require "rubygems"; rescue LoadError; return; end
+
+ stubs = %w(rails activesupport activerecord actionpack actionmailer activeresource)
+ stubs.reject! { |s| Gem.loaded_specs.key?(s) }
+
+ stubs.each do |stub|
+ Gem.loaded_specs[stub] = Gem::Specification.new do |s|
+ s.name = stub
+ s.version = Rails::VERSION::STRING
+ end
+ end
+ end
+ end
+
# Set the <tt>$LOAD_PATH</tt> based on the value of
# Configuration#load_paths. Duplicates are removed.
def set_load_path
@@ -666,7 +687,9 @@ module Rails
end
def default_plugin_locators
- [Plugin::FileSystemLocator]
+ locators = []
+ locators << Plugin::GemLocator if defined? Gem
+ locators << Plugin::FileSystemLocator
end
def default_plugin_loader
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 03fa309ca3..b45ec7de0e 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -97,4 +97,24 @@ module Rails
end
end
end
+
+ # This Plugin subclass represents a Gem plugin. It behaves exactly like a
+ # "traditional" Rails plugin, but doesn't expose any additional load paths,
+ # since RubyGems has already taken care of things.
+ class GemPlugin < Plugin
+
+ # Initialize this plugin from a Gem::Specification.
+ def initialize(spec)
+ super(File.join(spec.full_gem_path, "rails"))
+ @name = spec.name
+ end
+
+ def valid?
+ true
+ end
+
+ def load_paths
+ []
+ end
+ end
end \ No newline at end of file
diff --git a/railties/lib/rails/plugin/locator.rb b/railties/lib/rails/plugin/locator.rb
index b27e904b12..0b7923cfb6 100644
--- a/railties/lib/rails/plugin/locator.rb
+++ b/railties/lib/rails/plugin/locator.rb
@@ -72,7 +72,26 @@ module Rails
plugins
end
end
-
+ end
+
+ # The GemLocator scans all the loaded RubyGems, looking for gems with
+ # a <tt>rails/init.rb</tt> file.
+ class GemLocator < Locator
+ def plugins
+ specs = Gem.loaded_specs.values.select do |spec|
+ spec.loaded_from && # prune stubs
+ File.exist?(File.join(spec.full_gem_path, "rails", "init.rb"))
+ end
+
+ require "rubygems/dependency_list"
+
+ deps = Gem::DependencyList.new
+ deps.add(*specs)
+
+ deps.dependency_order.collect do |spec|
+ Rails::GemPlugin.new(spec)
+ end
+ end
end
end
end \ No newline at end of file