From 8301ce4d0b9de4423b74abf842faa6cf9e5aae1b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 27 Mar 2008 18:37:53 +0000 Subject: Added that gems can now be plugins if they include rails/init.rb (closes #11444) [jbarnette] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@9101 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- railties/CHANGELOG | 2 ++ railties/environments/boot.rb | 1 + railties/lib/initializer.rb | 25 ++++++++++++++++++++++++- railties/lib/rails/plugin.rb | 20 ++++++++++++++++++++ railties/lib/rails/plugin/locator.rb | 21 ++++++++++++++++++++- 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 $LOAD_PATH 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 rails/init.rb 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 -- cgit v1.2.3