diff options
author | Rick Olson <technoweenie@gmail.com> | 2008-03-30 02:17:28 +0000 |
---|---|---|
committer | Rick Olson <technoweenie@gmail.com> | 2008-03-30 02:17:28 +0000 |
commit | 088ef182e3006294b8f0e9b185d272a777c4437a (patch) | |
tree | 11b760af7a23bb5280f5aef5dc61350d0ea302f1 | |
parent | 81286f858770e0b95e15af37f19156b044ec6a95 (diff) | |
download | rails-088ef182e3006294b8f0e9b185d272a777c4437a.tar.gz rails-088ef182e3006294b8f0e9b185d272a777c4437a.tar.bz2 rails-088ef182e3006294b8f0e9b185d272a777c4437a.zip |
Added config.gem for specifying which gems are required by the application, as well as rake tasks for installing and freezing gems. [rick]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@9140 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r-- | railties/CHANGELOG | 17 | ||||
-rw-r--r-- | railties/lib/initializer.rb | 45 | ||||
-rw-r--r-- | railties/lib/rails/gem_dependency.rb | 78 | ||||
-rw-r--r-- | railties/lib/tasks/gems.rake | 31 | ||||
-rw-r--r-- | railties/test/gem_dependency_test.rb | 62 |
5 files changed, 231 insertions, 2 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 672131b96e..7950e6a14f 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,22 @@ *SVN* +* Added config.gem for specifying which gems are required by the application, as well as rake tasks for installing and freezing gems. [rick] + + Rails::Initializer.run do |config| + config.gems "bj" + config.gems "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" + config.gems "aws-s3", :lib => "aws/s3" + end + + # List required gems. + rake gems + + # Install all required gems: + rake gems:install + + # Unpack specified gem to vendor/gems/gem_name-x.x.x + rake gems:unpack GEM=bj + * Removed the default .htaccess configuration as there are so many good deployment options now (kept it as an example in README) [DHH] * config.time_zone accepts TZInfo::Timezone identifiers as well as Rails TimeZone identifiers [Geoff Buesing] diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index c60fe3d700..4be7b06f93 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -7,6 +7,7 @@ require 'railties_path' require 'rails/version' require 'rails/plugin/locator' require 'rails/plugin/loader' +require 'rails/gem_dependency' RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) @@ -77,6 +78,7 @@ module Rails require_frameworks set_autoload_paths + add_gem_load_paths add_plugin_load_paths load_environment @@ -98,8 +100,8 @@ module Rails add_support_load_paths + load_gems load_plugins - load_application_initializers # the framework is now fully initialized @@ -185,6 +187,17 @@ module Rails plugin_loader.add_plugin_load_paths end + def add_gem_load_paths + unless @configuration.gems.empty? + require "rubygems" + @configuration.gems.each &:add_load_paths + end + end + + def load_gems + @configuration.gems.each &:load + end + # Loads all plugins in <tt>config.plugin_paths</tt>. <tt>plugin_paths</tt> # defaults to <tt>vendor/plugins</tt> but may also be set to a list of # paths, such as @@ -229,7 +242,11 @@ module Rails def load_observers if configuration.frameworks.include?(:active_record) - ActiveRecord::Base.instantiate_observers + if @configuration.gems.any? { |g| !g.loaded? } + puts "Unable to instantiate observers, some gems that this application depends on are missing. Run 'rake gems:install'" + else + ActiveRecord::Base.instantiate_observers + end end end @@ -494,6 +511,25 @@ module Rails # a sub class would have access to fine grained modification of the loading behavior. See # the implementation of Rails::Plugin::Loader for more details. attr_accessor :plugin_loader + + # An array of gems that this rails application depends on. Rails will automatically load + # these gems during installation, and allow you to install any missing gems with: + # + # rake gems:install + # + # You can add with the #gem method. + attr_accessor :gems + + # Adds a single Gem dependency to the rails application. + # + # # gem 'aws-s3', '>= 0.4.0' + # # require 'aws/s3' + # config.gem 'aws-s3', :lib => 'aws/s3', :version => '>= 0.4.0', \ + # :source => "http://code.whytheluckystiff.net" + # + def gem(name, options = {}) + @gems << Rails::GemDependency.new(name, options) + end # Deprecated options: def breakpoint_server(_ = nil) @@ -529,6 +565,7 @@ module Rails self.plugin_locators = default_plugin_locators self.plugin_loader = default_plugin_loader self.database_configuration_file = default_database_configuration_file + self.gems = default_gems for framework in default_frameworks self.send("#{framework}=", Rails::OrderedOptions.new) @@ -712,6 +749,10 @@ module Rails :memory_store end end + + def default_gems + [] + end end end diff --git a/railties/lib/rails/gem_dependency.rb b/railties/lib/rails/gem_dependency.rb new file mode 100644 index 0000000000..ed16464887 --- /dev/null +++ b/railties/lib/rails/gem_dependency.rb @@ -0,0 +1,78 @@ +module Rails + class GemDependency + attr_accessor :name, :requirement, :version, :lib, :source + + def self.unpacked_path + @unpacked_path ||= File.join(RAILS_ROOT, 'vendor', 'gems') + end + + def initialize(name, options = {}) + @name = name.to_s + if options[:version] + @requirement = Gem::Requirement.create(options[:version]) + @version = @requirement.requirements.first.last + end + @lib = options[:lib] + @source = options[:source] + @loaded = false + @load_paths_added = false + @unpack_directory = nil + end + + def add_load_paths + return if @loaded || @load_paths_added + unpacked_paths = Dir[File.join(self.class.unpacked_path, "#{@name}-#{@version || "*"}")] + if unpacked_paths.empty? + args = [@name] + args << @requirement.to_s if @requirement + gem *args + else + $LOAD_PATH << File.join(unpacked_paths.first, 'lib') + end + @load_paths_added = true + rescue Gem::LoadError + puts $!.to_s + end + + def load + return if @load_paths_added == false + require(@lib || @name) + @loaded = true + rescue LoadError + puts $!.to_s + $!.backtrace.each { |b| puts b } + end + + def loaded? + @loaded + end + + def load_paths_added? + @load_paths_added + end + + def install + Gem::GemRunner.new.run(install_command) + end + + def unpack_to(directory) + FileUtils.mkdir_p directory + Dir.chdir directory do + Gem::GemRunner.new.run(unpack_command) + end + end + + def install_command + cmd = %w(install) << @name + cmd << "--version" << "#{@requirement.to_s}" if @requirement + cmd << "--source" << @source if @source + cmd + end + + def unpack_command + cmd = %w(unpack) << @name + cmd << "--version" << "#{@requirement.to_s}" if @requirement + cmd + end + end +end
\ No newline at end of file diff --git a/railties/lib/tasks/gems.rake b/railties/lib/tasks/gems.rake new file mode 100644 index 0000000000..198f6050c3 --- /dev/null +++ b/railties/lib/tasks/gems.rake @@ -0,0 +1,31 @@ +desc "List the gems that this rails application depends on" +task :gems => :environment do + Rails.configuration.gems.each do |gem| + puts "[#{gem.loaded? ? '*' : ' '}] #{gem.name} #{gem.requirement.to_s}" + end +end + +namespace :gems do + desc "Installs all required gems for this application." + task :install => :environment do + require 'rubygems' + require 'rubygems/gem_runner' + Rails.configuration.gems.each { |gem| gem.install unless gem.loaded? } + end + + desc "Unpacks the specified gem into vendor/gems." + task :unpack do + raise "Specify name of gem in the config.gems array with GEM=" if ENV['GEM'].blank? + Rake::Task["environment"].invoke + require 'rubygems' + require 'rubygems/gem_runner' + unless Rails.configuration.gems.select do |gem| + if gem.loaded? && gem.name == ENV['GEM'] + gem.unpack_to(File.join(RAILS_ROOT, 'vendor', 'gems')) + true + end + end.any? + puts "No gem named #{ENV['GEM'].inspect} found." + end + end +end
\ No newline at end of file diff --git a/railties/test/gem_dependency_test.rb b/railties/test/gem_dependency_test.rb new file mode 100644 index 0000000000..887ad53589 --- /dev/null +++ b/railties/test/gem_dependency_test.rb @@ -0,0 +1,62 @@ +require 'plugin_test_helper' + +uses_mocha "Plugin Tests" do + class GemDependencyTest < Test::Unit::TestCase + def setup + @gem = Rails::GemDependency.new "hpricot" + @gem_with_source = Rails::GemDependency.new "hpricot", :source => "http://code.whytheluckystiff.net" + @gem_with_version = Rails::GemDependency.new "hpricot", :version => "= 0.6" + @gem_with_lib = Rails::GemDependency.new "aws-s3", :lib => "aws/s3" + end + + def test_configuration_adds_gem_dependency + config = Rails::Configuration.new + config.gem "aws-s3", :lib => "aws/s3", :version => "0.4.0" + assert_equal [["install", "aws-s3", "--version", "= 0.4.0"]], config.gems.collect(&:install_command) + end + + def test_gem_creates_install_command + assert_equal %w(install hpricot), @gem.install_command + end + + def test_gem_with_source_creates_install_command + assert_equal %w(install hpricot --source http://code.whytheluckystiff.net), @gem_with_source.install_command + end + + def test_gem_with_version_creates_install_command + assert_equal ["install", "hpricot", "--version", "= 0.6"], @gem_with_version.install_command + end + + def test_gem_creates_unpack_command + assert_equal %w(unpack hpricot), @gem.unpack_command + end + + def test_gem_with_version_unpack_install_command + assert_equal ["unpack", "hpricot", "--version", "= 0.6"], @gem_with_version.unpack_command + end + + def test_gem_adds_load_paths + @gem.expects(:gem).with(@gem.name) + @gem.add_load_paths + end + + def test_gem_with_version_adds_load_paths + @gem_with_version.expects(:gem).with(@gem_with_version.name, @gem_with_version.requirement.to_s) + @gem_with_version.add_load_paths + end + + def test_gem_loading + @gem.expects(:gem).with(@gem.name) + @gem.expects(:require).with(@gem.name) + @gem.add_load_paths + @gem.load + end + + def test_gem_with_lib_loading + @gem_with_lib.expects(:gem).with(@gem_with_lib.name) + @gem_with_lib.expects(:require).with(@gem_with_lib.lib) + @gem_with_lib.add_load_paths + @gem_with_lib.load + end + end +end
\ No newline at end of file |