+++ /dev/null
-require 'logger'
-
-# We need to know the version of Rails that we are running before we
-# can override any of the dependency stuff, since Rails' own behaviour
-# has changed over the various releases. We need to explicily make sure
-# that the Rails::VERSION constant is loaded, because such things could
-# not automatically be achieved prior to 1.1, and the location of the
-# file moved in 1.1.1!
-def load_rails_version
- # At this point, we can't even rely on RAILS_ROOT existing, so we have to figure
- # the path to RAILS_ROOT/vendor/rails manually
- rails_base = File.expand_path(
- File.join(File.dirname(__FILE__), # RAILS_ROOT/vendor/plugins/engines/lib
- '..', # RAILS_ROOT/vendor/plugins/engines
- '..', # RAILS_ROOT/vendor/plugins
- '..', # RAILS_ROOT/vendor
- 'rails', 'railties', 'lib')) # RAILS_ROOT/vendor/rails/railties/lib
- begin
- load File.join(rails_base, 'rails', 'version.rb')
- #puts 'loaded 1.1.1+ from vendor: ' + File.join(rails_base, 'rails', 'version.rb')
- rescue MissingSourceFile # this means they DON'T have Rails 1.1.1 or later installed in vendor
- begin
- load File.join(rails_base, 'rails_version.rb')
- #puts 'loaded 1.1.0- from vendor: ' + File.join(rails_base, 'rails_version.rb')
- rescue MissingSourceFile # this means they DON'T have Rails 1.1.0 or previous installed in vendor
- begin
- # try and load version information for Rails 1.1.1 or later from the $LOAD_PATH
- require 'rails/version'
- #puts 'required 1.1.1+ from load path'
- rescue LoadError
- # try and load version information for Rails 1.1.0 or previous from the $LOAD_PATH
- require 'rails_version'
- #puts 'required 1.1.0- from load path'
- end
- end
- end
-end
-
-# Actually perform the load
-load_rails_version
-#puts "Detected Rails version: #{Rails::VERSION::STRING}"
-
-require 'engines/ruby_extensions'
-# ... further files are required at the bottom of this file
-
-# Holds the Rails Engine loading logic and default constants
-module Engines
-
- class << self
- # Return the version string for this plugin
- def version
- "#{Version::Major}.#{Version::Minor}.#{Version::Release}"
- end
-
- # For holding the rails configuration object
- attr_accessor :rails_config
-
- # A flag to stop searching for views in the application
- attr_accessor :disable_app_views_loading
-
- # A flag to stop code being mixed in from the application
- attr_accessor :disable_app_code_mixing
- end
-
- # The DummyLogger is a class which might pass through to a real Logger
- # if one is assigned. However, it can gracefully swallow any logging calls
- # if there is now Logger assigned.
- class LoggerWrapper
- def initialize(logger=nil)
- set_logger(logger)
- end
- # Assign the 'real' Logger instance that this dummy instance wraps around.
- def set_logger(logger)
- @logger = logger
- end
- # log using the appropriate method if we have a logger
- # if we dont' have a logger, ignore completely.
- def method_missing(name, *args)
- if @logger && @logger.respond_to?(name)
- @logger.send(name, *args)
- end
- end
- end
-
- LOGGER = Engines::LoggerWrapper.new
-
- class << self
- # Create a new Logger instance for Engines, with the given outputter and level
- def create_logger(outputter=STDOUT, level=Logger::INFO)
- LOGGER.set_logger(Logger.new(outputter, level))
- end
- # Sets the Logger instance that Engines will use to send logging information to
- def set_logger(logger)
- Engines::LOGGER.set_logger(logger) # TODO: no need for Engines:: part
- end
- # Retrieves the current Logger instance
- def log
- Engines::LOGGER # TODO: no need for Engines:: part
- end
- alias :logger :log
- end
-
- # An array of active engines. This should be accessed via the Engines.active method.
- ActiveEngines = []
-
- # The root directory for engines
- config :root, File.join(RAILS_ROOT, "vendor", "plugins")
-
- # The name of the public folder under which engine files are copied
- config :public_dir, "engine_files"
-
- class << self
-
- # Initializes a Rails Engine by loading the engine's init.rb file and
- # ensuring that any engine controllers are added to the load path.
- # This will also copy any files in a directory named 'public'
- # into the public webserver directory. Example usage:
- #
- # Engines.start :login
- # Engines.start :login_engine # equivalent
- #
- # A list of engine names can be specified:
- #
- # Engines.start :login, :user, :wiki
- #
- # The engines will be loaded in the order given.
- # If no engine names are given, all engines will be started.
- #
- # Options can include:
- # * :copy_files => true | false
- #
- # Note that if a list of engines is given, the options will apply to ALL engines.
- def start(*args)
-
- options = (args.last.is_a? Hash) ? args.pop : {}
-
- if args.empty?
- start_all
- else
- args.each do |engine_name|
- start_engine(engine_name, options)
- end
- end
- end
-
- # Starts all available engines. Plugins are considered engines if they
- # include an init_engine.rb file, or they are named <something>_engine.
- def start_all
- plugins = Dir[File.join(config(:root), "*")]
- Engines.log.debug "considering plugins: #{plugins.inspect}"
- plugins.each { |plugin|
- engine_name = File.basename(plugin)
- if File.exist?(File.join(plugin, "init_engine.rb")) || # if the directory contains init_engine.rb
- (engine_name =~ /_engine$/) || # or it engines in '_engines'
- (engine_name =~ /_bundle$/) # or even ends in '_bundle'
-
- start(engine_name) # start the engine...
-
- end
- }
- end
-
- # Initialize the routing controller paths.
- def initialize_routing
- # See lib/engines/routing_extensions.rb for more information.
- ActionController::Routing.controller_paths = Engines.rails_config.controller_paths
- end
-
- def start_engine(engine_name, options={})
-
- # Create a new Engine and put this engine at the front of the ActiveEngines list
- current_engine = Engine.new(engine_name)
- Engines.active.unshift current_engine
- Engines.log.info "Starting engine '#{current_engine.name}' from '#{File.expand_path(current_engine.root)}'"
-
- # add the code directories of this engine to the load path
- add_engine_to_load_path(current_engine)
-
- # add the controller & component path to the Dependency system
- engine_controllers = File.join(current_engine.root, 'app', 'controllers')
- engine_components = File.join(current_engine.root, 'components')
-
-
- # This mechanism is no longer required in Rails trunk
- if Rails::VERSION::STRING =~ /^1.0/ && !Engines.config(:edge)
- Controllers.add_path(engine_controllers) if File.exist?(engine_controllers)
- Controllers.add_path(engine_components) if File.exist?(engine_components)
- else
- ActionController::Routing.controller_paths << engine_controllers
- ActionController::Routing.controller_paths << engine_components
- end
-
- # copy the files unless indicated otherwise
- if options[:copy_files] != false
- current_engine.mirror_engine_files
- end
-
- # load the engine's init.rb file
- startup_file = File.join(current_engine.root, "init_engine.rb")
- if File.exist?(startup_file)
- eval(IO.read(startup_file), binding, startup_file)
- # possibly use require_dependency? Hmm.
- else
- Engines.log.debug "No init_engines.rb file found for engine '#{current_engine.name}'..."
- end
- end
-
- # Adds all directories in the /app and /lib directories within the engine
- # to the load path
- def add_engine_to_load_path(engine)
-
- # remove the lib directory added by load_plugin, and place it in the corrent
- # location *after* the application/lib. This can be removed when
- # http://dev.rubyonrails.org/ticket/2910 is fixed.
- app_lib_index = $LOAD_PATH.index(File.join(RAILS_ROOT, "lib"))
- engine_lib = File.join(engine.root, "lib")
- if app_lib_index
- $LOAD_PATH.delete(engine_lib)
- $LOAD_PATH.insert(app_lib_index+1, engine_lib)
- end
-
- # Add ALL paths under the engine root to the load path
- app_dirs = %w(controllers helpers models).collect { |d|
- File.join(engine.root, 'app', d)
- }
- other_dirs = %w(components lib).collect { |d|
- File.join(engine.root, d)
- }
- load_paths = (app_dirs + other_dirs).select { |d| File.directory?(d) }
-
- # Remove other engines from the $LOAD_PATH by matching against the engine.root values
- # in ActiveEngines. Store the removed engines in the order they came off.
-
- old_plugin_paths = []
- # assumes that all engines are at the bottom of the $LOAD_PATH
- while (File.expand_path($LOAD_PATH.last).index(File.expand_path(Engines.config(:root))) == 0) do
- old_plugin_paths.unshift($LOAD_PATH.pop)
- end
-
-
- # add these LAST on the load path.
- load_paths.reverse.each { |dir|
- if File.directory?(dir)
- Engines.log.debug "adding #{File.expand_path(dir)} to the load path"
- #$LOAD_PATH.push(File.expand_path(dir))
- $LOAD_PATH.push dir
- end
- }
-
- # Add the other engines back onto the bottom of the $LOAD_PATH. Put them back on in
- # the same order.
- $LOAD_PATH.push(*old_plugin_paths)
- $LOAD_PATH.uniq!
- end
-
- # Returns the directory in which all engine public assets are mirrored.
- def public_engine_dir
- File.expand_path(File.join(RAILS_ROOT, "public", Engines.config(:public_dir)))
- end
-
- # create the /public/engine_files directory if it doesn't exist
- def create_base_public_directory
- if !File.exists?(public_engine_dir)
- # create the public/engines directory, with a warning message in it.
- Engines.log.debug "Creating public engine files directory '#{public_engine_dir}'"
- FileUtils.mkdir(public_engine_dir)
- File.open(File.join(public_engine_dir, "README"), "w") do |f|
- f.puts <<EOS
-Files in this directory are automatically generated from your Rails Engines.
-They are copied from the 'public' directories of each engine into this directory
-each time Rails starts (server, console... any time 'start_engine' is called).
-Any edits you make will NOT persist across the next server restart; instead you
-should edit the files within the <engine_name>/public/ directory itself.
-EOS
- end
- end
- end
-
- # Returns the Engine object for the specified engine, e.g.:
- # Engines.get(:login)
- def get(name)
- active.find { |e| e.name == name.to_s || e.name == "#{name}_engine" }
- end
- alias_method :[], :get
-
- # Returns the Engine object for the current engine, i.e. the engine
- # in which the currently executing code lies.
- def current
- current_file = caller[0]
- active.find do |engine|
- File.expand_path(current_file).index(File.expand_path(engine.root)) == 0
- end
- end
-
- # Returns an array of active engines
- def active
- ActiveEngines
- end
-
- # Pass a block to perform an operation on each engine. You may pass an argument
- # to determine the order:
- #
- # * :load_order - in the order they were loaded (i.e. lower precidence engines first).
- # * :precidence_order - highest precidence order (i.e. last loaded) first
- def each(ordering=:precidence_order, &block)
- engines = (ordering == :load_order) ? active.reverse : active
- engines.each { |e| yield e }
- end
- end
-end
-
-# A simple class for holding information about loaded engines
-class Engine
-
- # Returns the base path of this engine
- attr_accessor :root
-
- # Returns the name of this engine
- attr_reader :name
-
- # An attribute for holding the current version of this engine. There are three
- # ways of providing an engine version. The simplest is using a string:
- #
- # Engines.current.version = "1.0.7"
- #
- # Alternatively you can set it to a module which contains Major, Minor and Release
- # constants:
- #
- # module LoginEngine::Version
- # Major = 1; Minor = 0; Release = 6;
- # end
- # Engines.current.version = LoginEngine::Version
- #
- # Finally, you can set it to your own Proc, if you need something really fancy:
- #
- # Engines.current.version = Proc.new { File.open('VERSION', 'r').readlines[0] }
- #
- attr_writer :version
-
- # Engine developers can store any information they like in here.
- attr_writer :info
-
- # Creates a new object holding information about an Engine.
- def initialize(name)
-
- @root = ''
- suffixes = ['', '_engine', '_bundle']
- while !File.exist?(@root) && !suffixes.empty?
- suffix = suffixes.shift
- @root = File.join(Engines.config(:root), name.to_s + suffix)
- end
-
- if !File.exist?(@root)
- raise "Cannot find the engine '#{name}' in either /vendor/plugins/#{name}, " +
- "/vendor/plugins/#{name}_engine or /vendor/plugins/#{name}_bundle."
- end
-
- @name = File.basename(@root)
- end
-
- # Returns the version string of this engine
- def version
- case @version
- when Module
- "#{@version::Major}.#{@version::Minor}.#{@version::Release}"
- when Proc # not sure about this
- @version.call
- when NilClass
- 'unknown'
- else
- @version
- end
- end
-
- # Returns a string describing this engine
- def info
- @info || '(none)'
- end
-
- # Returns a string representation of this engine
- def to_s
- "Engine<'#{@name}' [#{version}]:#{root.gsub(RAILS_ROOT, '')}>"
- end
-
- # return the path to this Engine's public files (with a leading '/' for use in URIs)
- def public_dir
- File.join("/", Engines.config(:public_dir), name)
- end
-
- # Replicates the subdirectories under the engine's /public directory into
- # the corresponding public directory.
- def mirror_engine_files
-
- begin
- Engines.create_base_public_directory
-
- source = File.join(root, "public")
- Engines.log.debug "Attempting to copy public engine files from '#{source}'"
-
- # if there is no public directory, just return after this file
- return if !File.exist?(source)
-
- source_files = Dir[source + "/**/*"]
- source_dirs = source_files.select { |d| File.directory?(d) }
- source_files -= source_dirs
-
- Engines.log.debug "source dirs: #{source_dirs.inspect}"
-
- # Create the engine_files/<something>_engine dir if it doesn't exist
- new_engine_dir = File.join(RAILS_ROOT, "public", public_dir)
- if !File.exists?(new_engine_dir)
- # Create <something>_engine dir with a message
- Engines.log.debug "Creating #{public_dir} public dir"
- FileUtils.mkdir_p(new_engine_dir)
- end
-
- # create all the directories, transforming the old path into the new path
- source_dirs.uniq.each { |dir|
- begin
- # strip out the base path and add the result to the public path, i.e. replace
- # ../script/../vendor/plugins/engine_name/public/javascript
- # with
- # engine_name/javascript
- #
- relative_dir = dir.gsub(File.join(root, "public"), name)
- target_dir = File.join(Engines.public_engine_dir, relative_dir)
- unless File.exist?(target_dir)
- Engines.log.debug "creating directory '#{target_dir}'"
- FileUtils.mkdir_p(target_dir)
- end
- rescue Exception => e
- raise "Could not create directory #{target_dir}: \n" + e
- end
- }
-
- # copy all the files, transforming the old path into the new path
- source_files.uniq.each { |file|
- begin
- # change the path from the ENGINE ROOT to the public directory root for this engine
- target = file.gsub(File.join(root, "public"),
- File.join(Engines.public_engine_dir, name))
- unless File.exist?(target) && FileUtils.identical?(file, target)
- Engines.log.debug "copying file '#{file}' to '#{target}'"
- FileUtils.cp(file, target)
- end
- rescue Exception => e
- raise "Could not copy #{file} to #{target}: \n" + e
- end
- }
- rescue Exception => e
- Engines.log.warn "WARNING: Couldn't create the engine public file structure for engine '#{name}'; Error follows:"
- Engines.log.warn e
- end
- end
-end
-
-
-# These files must be required after the Engines module has been defined.
-require 'engines/dependencies_extensions'
-require 'engines/routing_extensions'
-require 'engines/action_view_extensions'
-require 'engines/action_mailer_extensions'
-require 'engines/migration_extensions'
-require 'engines/active_record_extensions'
-
-# only load the testing extensions if we are in the test environment
-require 'engines/testing_extensions' if %w(test).include?(RAILS_ENV)