From 088ef182e3006294b8f0e9b185d272a777c4437a Mon Sep 17 00:00:00 2001 From: Rick Olson Date: Sun, 30 Mar 2008 02:17:28 +0000 Subject: 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 --- railties/lib/initializer.rb | 45 ++++++++++++++++++++- railties/lib/rails/gem_dependency.rb | 78 ++++++++++++++++++++++++++++++++++++ railties/lib/tasks/gems.rake | 31 ++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 railties/lib/rails/gem_dependency.rb create mode 100644 railties/lib/tasks/gems.rake (limited to 'railties/lib') 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 config.plugin_paths. plugin_paths # defaults to vendor/plugins 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 -- cgit v1.2.3