aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/initializer.rb45
-rw-r--r--railties/lib/rails/gem_dependency.rb78
-rw-r--r--railties/lib/tasks/gems.rake31
3 files changed, 152 insertions, 2 deletions
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