Permalink
Browse files

Added config.gem for specifying which gems are required by the applic…

…ation, 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
  • Loading branch information...
technoweenie committed Mar 30, 2008
1 parent 81286f8 commit 088ef182e3006294b8f0e9b185d272a777c4437a
@@ -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]
@@ -7,6 +7,7 @@
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 @@ def process

require_frameworks
set_autoload_paths
add_gem_load_paths
add_plugin_load_paths
load_environment

@@ -98,8 +100,8 @@ def process

add_support_load_paths

load_gems
load_plugins

load_application_initializers

# the framework is now fully initialized
@@ -185,6 +187,17 @@ def add_plugin_load_paths
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 @@ def load_environment

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 @@ def plugins=(plugins)
# 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 @@ def initialize
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 @@ def default_cache_store
:memory_store
end
end

def default_gems
[]
end
end
end

@@ -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
@@ -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
@@ -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

0 comments on commit 088ef18

Please sign in to comment.