diff options
author | José Valim <jose.valim@gmail.com> | 2010-09-04 00:31:35 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-09-04 00:31:43 +0200 |
commit | 23a9455962f0362cf242ffa96db7a9e7fdb0804b (patch) | |
tree | c046d1285d078649db6833fa1b73a6c23f7f16ea /railties/lib/rails | |
parent | 63032c1162e96d3380168ca63ac42aa044dbebd6 (diff) | |
parent | c3c1a1e14859e6716970283caeab0c4c3720862e (diff) | |
download | rails-23a9455962f0362cf242ffa96db7a9e7fdb0804b.tar.gz rails-23a9455962f0362cf242ffa96db7a9e7fdb0804b.tar.bz2 rails-23a9455962f0362cf242ffa96db7a9e7fdb0804b.zip |
This commit merges most of the work done by Piotr Sarnacki in his Ruby Summer of Code project.
His work brings several capabilities from app to engines, as routes, middleware stack, asset handling and much more. Please check Rails::Engine documentation for more refenrences.
Merge remote branch 'drogus/engines'
Diffstat (limited to 'railties/lib/rails')
-rw-r--r-- | railties/lib/rails/application.rb | 66 | ||||
-rw-r--r-- | railties/lib/rails/application/bootstrap.rb | 7 | ||||
-rw-r--r-- | railties/lib/rails/application/configurable.rb | 19 | ||||
-rw-r--r-- | railties/lib/rails/application/configuration.rb | 32 | ||||
-rw-r--r-- | railties/lib/rails/application/railties.rb | 26 | ||||
-rw-r--r-- | railties/lib/rails/configuration.rb | 81 | ||||
-rw-r--r-- | railties/lib/rails/engine.rb | 278 | ||||
-rw-r--r-- | railties/lib/rails/engine/configurable.rb | 25 | ||||
-rw-r--r-- | railties/lib/rails/engine/configuration.rb | 12 | ||||
-rw-r--r-- | railties/lib/rails/engine/railties.rb | 23 | ||||
-rw-r--r-- | railties/lib/rails/plugin.rb | 15 | ||||
-rw-r--r-- | railties/lib/rails/railtie.rb | 29 | ||||
-rw-r--r-- | railties/lib/rails/railtie/configurable.rb | 26 | ||||
-rw-r--r-- | railties/lib/rails/railtie/configuration.rb | 10 |
14 files changed, 412 insertions, 237 deletions
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 5b26333486..8631a5df3e 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -41,24 +41,6 @@ module Rails autoload :Railties, 'rails/application/railties' class << self - private :new - - def configure(&block) - class_eval(&block) - end - - def instance - if self == Rails::Application - if Rails.application - ActiveSupport::Deprecation.warn "Calling a method in Rails::Application is deprecated, " << - "please call it directly in your application constant #{Rails.application.class.name}.", caller - end - Rails.application - else - @@instance ||= new - end - end - def inherited(base) raise "You cannot have more than one Rails::Application" if Rails.application super @@ -66,19 +48,9 @@ module Rails Rails.application.add_lib_to_load_path! ActiveSupport.run_load_hooks(:before_configuration, base.instance) end - - def respond_to?(*args) - super || instance.respond_to?(*args) - end - - protected - - def method_missing(*args, &block) - instance.send(*args, &block) - end end - delegate :middleware, :to => :config + delegate :default_url_options, :default_url_options=, :to => :routes # This method is called just after an application inherits from Rails::Application, # allowing the developer to load classes in lib and use them during application @@ -108,14 +80,6 @@ module Rails super end - def routes - @routes ||= ActionDispatch::Routing::RouteSet.new - end - - def railties - @railties ||= Railties.new(config) - end - def routes_reloader @routes_reloader ||= ActiveSupport::FileUpdateChecker.new([]){ reload_routes! } end @@ -131,7 +95,9 @@ module Rails end def initialize! + raise "Application has been already initialized." if @initialized run_initializers(self) + @initialized = true self end @@ -156,38 +122,32 @@ module Rails self end - def app - @app ||= begin - config.middleware = config.middleware.merge_into(default_middleware_stack) - config.middleware.build(routes) - end - end alias :build_middleware_stack :app - def call(env) - app.call(env.reverse_merge!(env_defaults)) - end - - def env_defaults - @env_defaults ||= { + def env_config + @env_config ||= super.merge({ "action_dispatch.parameter_filter" => config.filter_parameters, - "action_dispatch.secret_token" => config.secret_token - } + "action_dispatch.secret_token" => config.secret_token, + "action_dispatch.asset_path" => nil + }) end def initializers initializers = Bootstrap.initializers_for(self) - railties.all { |r| initializers += r.initializers } initializers += super initializers += Finisher.initializers_for(self) initializers end + def config + @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) + end + protected def default_middleware_stack ActionDispatch::MiddlewareStack.new.tap do |middleware| - middleware.use ::ActionDispatch::Static, paths.public.to_a.first if config.serve_static_assets + middleware.use ::ActionDispatch::Static, config.static_asset_paths if config.serve_static_assets middleware.use ::Rack::Lock if !config.allow_concurrency middleware.use ::Rack::Runtime middleware.use ::Rails::Rack::Logger diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index 44e26b5713..e39b3bc705 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -6,10 +6,7 @@ module Rails module Bootstrap include Initializable - initializer :load_environment_config do - environment = config.paths.config.environments.to_a.first - require environment if environment - end + initializer :load_environment_hook do end initializer :load_active_support do require 'active_support/dependencies' @@ -73,4 +70,4 @@ module Rails end end end -end
\ No newline at end of file +end diff --git a/railties/lib/rails/application/configurable.rb b/railties/lib/rails/application/configurable.rb deleted file mode 100644 index f598e33965..0000000000 --- a/railties/lib/rails/application/configurable.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Rails - class Application - module Configurable - def self.included(base) - base.extend ClassMethods - end - - module ClassMethods - def inherited(base) - raise "You cannot inherit from a Rails::Application child" - end - end - - def config - @config ||= Application::Configuration.new(self.class.find_root_with_flag("config.ru", Dir.pwd)) - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index c3418e0d80..477bbbc1e7 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -1,16 +1,13 @@ -require 'active_support/deprecation' require 'active_support/core_ext/string/encoding' require 'rails/engine/configuration' module Rails class Application class Configuration < ::Rails::Engine::Configuration - include ::Rails::Configuration::Deprecated - attr_accessor :allow_concurrency, :cache_classes, :cache_store, :encoding, :consider_all_requests_local, :dependency_loading, - :filter_parameters, :log_level, :logger, :middleware, - :plugins, :preload_frameworks, :reload_plugins, + :filter_parameters, :log_level, :logger, + :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, :time_zone, :whiny_nils @@ -28,6 +25,22 @@ module Rails @middleware = app_middleware end + def asset_path=(value) + action_mailer.asset_path = value if respond_to?(:action_mailer) && action_mailer + action_controller.asset_path = value if respond_to?(:action_controller) && action_controller + super(value) + end + + def asset_host=(value) + action_mailer.asset_host = value if action_mailer + action_controller.asset_host = value if action_controller + super(value) + end + + def compiled_asset_path + "/" + end + def encoding=(value) @encoding = value if "ruby".encoding_aware? @@ -48,19 +61,10 @@ module Rails paths.app.controllers << builtin_controller if builtin_controller paths.config.database "config/database.yml" paths.config.environment "config/environment.rb" - paths.config.environments "config/environments", :glob => "#{Rails.env}.rb" paths.lib.templates "lib/templates" paths.log "log/#{Rails.env}.log" paths.tmp "tmp" paths.tmp.cache "tmp/cache" - paths.vendor "vendor", :load_path => true - paths.vendor.plugins "vendor/plugins" - - if File.exists?("#{root}/test/mocks/#{Rails.env}") - ActiveSupport::Deprecation.warn "\"Rails.root/test/mocks/#{Rails.env}\" won't be added " << - "automatically to load paths anymore in future releases" - paths.mocks_path "test/mocks", :autoload => true, :glob => Rails.env - end paths end diff --git a/railties/lib/rails/application/railties.rb b/railties/lib/rails/application/railties.rb index b3e6693f89..c1d2de571f 100644 --- a/railties/lib/rails/application/railties.rb +++ b/railties/lib/rails/application/railties.rb @@ -1,31 +1,21 @@ -module Rails - class Application - class Railties - # TODO Write tests for this behavior extracted from Application - def initialize(config) - @config = config - end +require 'rails/engine/railties' +module Rails + class Application < Engine + class Railties < Rails::Engine::Railties def all(&block) - @all ||= railties + engines + plugins + @all ||= railties + engines + super @all.each(&block) if block @all end def railties - @railties ||= ::Rails::Railtie.subclasses.map(&:new) + @railties ||= ::Rails::Railtie.subclasses.map(&:instance) end def engines - @engines ||= ::Rails::Engine.subclasses.map(&:new) - end - - def plugins - @plugins ||= begin - plugin_names = (@config.plugins || [:all]).map { |p| p.to_sym } - Plugin.all(plugin_names, @config.paths.vendor.plugins) - end + @engines ||= ::Rails::Engine.subclasses.map(&:instance) end end end -end
\ No newline at end of file +end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index e5af12b901..8369795e71 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -71,86 +71,5 @@ module Rails end end end - - module Deprecated - def frameworks(*args) - raise "config.frameworks in no longer supported. See the generated " \ - "config/boot.rb for steps on how to limit the frameworks that " \ - "will be loaded" - end - alias :frameworks= :frameworks - - def view_path=(value) - ActiveSupport::Deprecation.warn "config.view_path= is deprecated, " << - "please do paths.app.views= instead", caller - paths.app.views = value - end - - def view_path - ActiveSupport::Deprecation.warn "config.view_path is deprecated, " << - "please do paths.app.views instead", caller - paths.app.views.to_a.first - end - - def routes_configuration_file=(value) - ActiveSupport::Deprecation.warn "config.routes_configuration_file= is deprecated, " << - "please do paths.config.routes= instead", caller - paths.config.routes = value - end - - def routes_configuration_file - ActiveSupport::Deprecation.warn "config.routes_configuration_file is deprecated, " << - "please do paths.config.routes instead", caller - paths.config.routes.to_a.first - end - - def database_configuration_file=(value) - ActiveSupport::Deprecation.warn "config.database_configuration_file= is deprecated, " << - "please do paths.config.database= instead", caller - paths.config.database = value - end - - def database_configuration_file - ActiveSupport::Deprecation.warn "config.database_configuration_file is deprecated, " << - "please do paths.config.database instead", caller - paths.config.database.to_a.first - end - - def log_path=(value) - ActiveSupport::Deprecation.warn "config.log_path= is deprecated, " << - "please do paths.log= instead", caller - paths.config.log = value - end - - def log_path - ActiveSupport::Deprecation.warn "config.log_path is deprecated, " << - "please do paths.log instead", caller - paths.config.log.to_a.first - end - - def controller_paths=(value) - ActiveSupport::Deprecation.warn "config.controller_paths= is deprecated, " << - "please do paths.app.controllers= instead", caller - paths.app.controllers = value - end - - def controller_paths - ActiveSupport::Deprecation.warn "config.controller_paths is deprecated, " << - "please do paths.app.controllers instead", caller - paths.app.controllers.to_a.uniq - end - - def cookie_secret=(value) - ActiveSupport::Deprecation.warn "config.cookie_secret= is deprecated, " << - "please use config.secret_token= instead", caller - self.secret_token = value - end - - def cookie_secret - ActiveSupport::Deprecation.warn "config.cookie_secret is deprecated, " << - "please use config.secret_token instead", caller - self.secret_token - end - end end end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 555bc9dbc8..e10980a6d9 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -2,6 +2,7 @@ require 'rails/railtie' require 'active_support/core_ext/module/delegation' require 'pathname' require 'rbconfig' +require 'rails/engine/railties' module Rails # Rails::Engine allows you to wrap a specific Rails application and share it accross @@ -86,14 +87,172 @@ module Rails # all folders under "app" are automatically added to the load path. So if you have # "app/observers", it's added by default. # + # == Endpoint + # + # Engine can be also a rack application. It can be useful if you have a rack application that + # you would like to wrap with Engine and provide some of the Engine's features. + # + # To do that, use endpoint method: + # module MyEngine + # class Engine < Rails::Engine + # endpoint MyRackApplication + # end + # end + # + # Now you can mount your engine in application's routes just like that: + # + # MyRailsApp::Application.routes.draw do + # mount MyEngine::Engine => "/engine" + # end + # + # == Middleware stack + # + # As Engine can now be rack endpoint, it can also have a middleware stack. The usage is exactly + # the same as in application: + # + # module MyEngine + # class Engine < Rails::Engine + # middleware.use SomeMiddleware + # end + # end + # + # == Routes + # + # If you don't specify endpoint, routes will be used as default endpoint. You can use them + # just like you use application's routes: + # + # # ENGINE/config/routes.rb + # MyEngine::Engine.routes.draw do + # match "/" => "posts#index" + # end + # + # == Mount priority + # + # Note that now there can be more than one router in you application and it's better to avoid + # passing requests through many routers. Consider such situation: + # + # MyRailsApp::Application.routes.draw do + # mount MyEngine::Engine => "/blog" + # match "/blog/omg" => "main#omg" + # end + # + # MyEngine is mounted at "/blog" path and additionaly "/blog/omg" points application's controller. + # In such situation request to "/blog/omg" will go through MyEngine and if there is no such route + # in Engine's routes, it will be dispatched to "main#omg". It's much better to swap that: + # + # MyRailsApp::Application.routes.draw do + # match "/blog/omg" => "main#omg" + # mount MyEngine::Engine => "/blog" + # end + # + # Now, Engine will get only requests that were not handled by application. + # + # == Asset path + # + # When you use engine with its own public directory, you will probably want to copy or symlink it + # to application's public directory. To simplify generating paths for assets, you can set asset_path + # for an Engine: + # + # module MyEngine + # class Engine < Rails::Engine + # config.asset_path = "/my_engine/%s" + # end + # end + # + # With such config, asset paths will be automatically modified inside Engine: + # image_path("foo.jpg") #=> "/my_engine/images/foo.jpg" + # + # == Engine name + # + # There are some places where engine's name is used. + # * routes: when you mount engine with mount(MyEngine::Engine => '/my_engine'), it's used as default :as option + # * migrations: when you copy engine's migrations, they will be decorated with suffix based on engine_name, for example: + # 2010010203121314_create_users.my_engine.rb + # + # Engine name is set by default based on class name. For MyEngine::Engine it will be my_engine_engine. + # You can change it manually it manually using engine_name method: + # + # module MyEngine + # class Engine < Rails::Engine + # engine_name "my_engine" + # end + # end + # + # == Namespaced Engine + # + # Normally, when you create controllers, helpers and models inside engine, they are treated + # as they would be created inside application. One of the cosequences of that is including + # application's helpers and url_helpers inside controller. Sometimes, especially when your + # engine provides its own routes, you don't want that. To isolate engine's stuff from application + # you can use namespace method: + # + # module MyEngine + # class Engine < Rails::Engine + # namespace MyEngine + # end + # end + # + # With such Engine, everything that is inside MyEngine module, will be isolated from application. + # + # Consider such controller: + # + # module MyEngine + # class FooController < ActionController::Base + # end + # end + # + # If engine is marked as namespaced, FooController has access only to helpers from engine and + # url_helpers from MyEngine::Engine.routes. + # + # Additionaly namespaced engine will set its name according to namespace, so in that case: + # MyEngine::Engine.engine_name #=> "my_engine" + # and it will set MyEngine.table_name_prefix to "my_engine_" + # + # == Using Engine's routes outside Engine + # + # Since you can mount engine inside application's routes now, you do not have direct access to engine's + # url_helpers inside application. When you mount Engine in application's routes special helper is + # created to allow doing that. Consider such scenario: + # + # # APP/config/routes.rb + # MyApplication::Application.routes.draw do + # mount MyEngine::Engine => "/my_engine", :as => "my_engine" + # match "/foo" => "foo#index" + # end + # + # Now, you can use my_engine helper: + # + # class FooController < ApplicationController + # def index + # my_engine.root_url #=> /my_engine/ + # end + # end + # + # There is also 'app' helper that gives you access to application's routes inside Engine: + # + # module MyEngine + # class BarController + # app.foo_path #=> /foo + # end + # end + # + # Note that :as option takes engine_name as default, so most of the time you can ommit it. + # + # If you want to generate url to engine's route using polymorphic_url, you can also use that helpers. + # + # Let's say that you want to create a form pointing to one of the engine's routes. All you need to do + # is passing helper as the first element in array with attributes for url: + # + # form_for([my_engine, @user]) + # + # This code will use my_engine.user_path(@user) to generate proper route. + # class Engine < Railtie autoload :Configurable, "rails/engine/configurable" autoload :Configuration, "rails/engine/configuration" class << self - attr_accessor :called_from - - # TODO Remove this. It's deprecated. + attr_accessor :called_from, :namespaced alias :engine_name :railtie_name def inherited(base) @@ -122,9 +281,40 @@ module Rails RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? Pathname.new(root).expand_path : Pathname.new(root).realpath end + + def endpoint(endpoint = nil) + @endpoint = endpoint if endpoint + @endpoint + end + + def namespace(mod) + # TODO: extract that into a module + engine_name(generate_railtie_name(mod)) + + _railtie = self + name = engine_name + mod.singleton_class.instance_eval do + define_method(:_railtie) do + _railtie + end + + define_method(:table_name_prefix) do + "#{name}_" + end + end + + self.routes.default_scope = {:module => name} + + self.namespaced = true + end + + def namespaced? + !!namespaced + end end - delegate :paths, :root, :to => :config + delegate :middleware, :root, :paths, :to => :config + delegate :engine_name, :namespaced?, :to => "self.class" def load_tasks super @@ -140,6 +330,47 @@ module Rails end end + def railties + @railties ||= self.class::Railties.new(config) + end + + def app + @app ||= begin + config.middleware = config.middleware.merge_into(default_middleware_stack) + config.middleware.build(endpoint) + end + end + + def endpoint + self.class.endpoint || routes + end + + def call(env) + app.call(env.merge!(env_config)) + end + + def env_config + @env_config ||= { + 'action_dispatch.routes' => routes, + 'action_dispatch.asset_path' => config.asset_path + } + end + + def routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + def initializers + initializers = [] + railties.all { |r| initializers += r.initializers } + initializers += super + initializers + end + + def config + @config ||= Engine::Configuration.new(find_root_with_flag("lib")) + end + # Add configured load paths to ruby load paths and remove duplicates. initializer :set_load_path, :before => :bootstrap_hook do _all_load_paths.reverse_each do |path| @@ -196,6 +427,27 @@ module Rails end end + initializer :load_environment_config, :before => :load_environment_hook do + environment = config.paths.config.environments.to_a.first + require environment if environment + end + + initializer :append_asset_paths do + config.asset_path = "/#{engine_name}%s" unless config.asset_path + + public_path = config.paths.public.to_a.first + if config.compiled_asset_path && File.exist?(public_path) + config.static_asset_paths[config.compiled_asset_path] = public_path + end + end + + initializer :prepend_helpers_path do + unless namespaced? + config.helpers_paths = [] unless config.respond_to?(:helpers_paths) + config.helpers_paths = config.paths.app.helpers.to_a + config.helpers_paths + end + end + initializer :load_config_initializers do paths.config.initializers.to_a.sort.each do |initializer| load(initializer) @@ -208,6 +460,24 @@ module Rails end protected + def find_root_with_flag(flag, default=nil) + root_path = self.class.called_from + + while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/#{flag}") + parent = File.dirname(root_path) + root_path = parent != root_path && parent + end + + root = File.exist?("#{root_path}/#{flag}") ? root_path : default + raise "Could not find root path for #{self}" unless root + + Config::CONFIG['host_os'] =~ /mswin|mingw/ ? + Pathname.new(root).expand_path : Pathname.new(root).realpath + end + + def default_middleware_stack + ActionDispatch::MiddlewareStack.new + end def _all_autoload_paths @_all_autoload_paths ||= (config.autoload_paths + config.eager_load_paths + config.autoload_once_paths).uniq diff --git a/railties/lib/rails/engine/configurable.rb b/railties/lib/rails/engine/configurable.rb deleted file mode 100644 index 9a370f0abb..0000000000 --- a/railties/lib/rails/engine/configurable.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Rails - class Engine - module Configurable - def self.included(base) - base.extend ClassMethods - end - - module ClassMethods - delegate :middleware, :root, :paths, :to => :config - - def config - @config ||= Engine::Configuration.new(find_root_with_flag("lib")) - end - - def inherited(base) - raise "You cannot inherit from a Rails::Engine child" - end - end - - def config - self.class.config - end - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 521ed95447..3ac8911ba8 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -5,10 +5,13 @@ module Rails class Configuration < ::Rails::Railtie::Configuration attr_reader :root attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths + attr_accessor :middleware, :plugins, :asset_path def initialize(root=nil) super() @root = root + @middleware = Rails::Configuration::MiddlewareStackProxy.new + @helpers_paths = [] end def paths @@ -26,9 +29,14 @@ module Rails paths.config.initializers "config/initializers", :glob => "**/*.rb" paths.config.locales "config/locales", :glob => "*.{rb,yml}" paths.config.routes "config/routes.rb" + paths.config.environments "config/environments", :glob => "#{Rails.env}.rb" paths.public "public" paths.public.javascripts "public/javascripts" paths.public.stylesheets "public/stylesheets" + paths.vendor "vendor", :load_path => true + paths.vendor.plugins "vendor/plugins" + paths.db "db" + paths.db.migrate "db/migrate" paths end end @@ -48,6 +56,10 @@ module Rails def autoload_paths @autoload_paths ||= paths.autoload_paths end + + def compiled_asset_path + asset_path % "" if asset_path + end end end end diff --git a/railties/lib/rails/engine/railties.rb b/railties/lib/rails/engine/railties.rb new file mode 100644 index 0000000000..389a7602c6 --- /dev/null +++ b/railties/lib/rails/engine/railties.rb @@ -0,0 +1,23 @@ +module Rails + class Engine < Railtie + class Railties + # TODO Write tests for this behavior extracted from Application + def initialize(config) + @config = config + end + + def all(&block) + @all ||= plugins + @all.each(&block) if block + @all + end + + def plugins + @plugins ||= begin + plugin_names = (@config.plugins || [:all]).map { |p| p.to_sym } + Plugin.all(plugin_names, @config.paths.vendor.plugins) + end + end + end + end +end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 8d5132a5ca..c07ff2f9cf 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -18,6 +18,10 @@ module Rails # root during the boot process. # class Plugin < Engine + def self.global_plugins + @global_plugins ||= [] + end + def self.inherited(base) raise "You cannot inherit from Rails::Plugin" end @@ -28,6 +32,11 @@ module Rails Dir["#{path}/*"].each do |plugin_path| plugin = new(plugin_path) next unless list.include?(plugin.name) || list.include?(:all) + if global_plugins.include?(plugin.name) + warn "WARNING: plugin #{plugin.name} from #{path} was not loaded. Plugin with the same name has been already loaded." + next + end + global_plugins << plugin.name plugins << plugin end end @@ -39,6 +48,10 @@ module Rails attr_reader :name, :path + def railtie_name + name.to_s + end + def load_tasks super load_deprecated_tasks @@ -78,6 +91,8 @@ module Rails ActiveSupport::Deprecation.warn "Use toplevel init.rb; rails/init.rb is deprecated: #{initrb}" end config = app.config + # TODO: think about evaling initrb in context of Engine (currently it's + # always evaled in context of Rails::Application) eval(File.read(initrb), binding, initrb) end end diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index 58b0d851f7..09650789ac 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -1,7 +1,6 @@ require 'rails/initializable' require 'rails/configuration' require 'active_support/inflector' -require 'active_support/deprecation' module Rails # Railtie is the core of the Rails Framework and provides several hooks to extend @@ -131,25 +130,19 @@ module Rails ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Plugin Rails::Engine Rails::Application) class << self + private :new + def subclasses @subclasses ||= [] end def inherited(base) unless base.abstract_railtie? - base.send(:include, self::Configurable) + base.send(:include, Railtie::Configurable) subclasses << base end end - def railtie_name(*) - ActiveSupport::Deprecation.warn "railtie_name is deprecated and has no effect", caller - end - - def log_subscriber(*) - ActiveSupport::Deprecation.warn "log_subscriber is deprecated and has no effect", caller - end - def rake_tasks(&blk) @rake_tasks ||= [] @rake_tasks << blk if blk @@ -171,6 +164,22 @@ module Rails def abstract_railtie? ABSTRACT_RAILTIES.include?(name) end + + def railtie_name(name = nil) + @railtie_name = name.to_s if name + @railtie_name ||= generate_railtie_name(self.name) + end + + protected + def generate_railtie_name(class_or_module) + ActiveSupport::Inflector.underscore(class_or_module).gsub("/", "_") + end + end + + delegate :railtie_name, :to => "self.class" + + def config + @config ||= Railtie::Configuration.new end def eager_load! diff --git a/railties/lib/rails/railtie/configurable.rb b/railties/lib/rails/railtie/configurable.rb index a2eb938c5a..b6d4ed2312 100644 --- a/railties/lib/rails/railtie/configurable.rb +++ b/railties/lib/rails/railtie/configurable.rb @@ -6,17 +6,29 @@ module Rails end module ClassMethods - def config - @config ||= Railtie::Configuration.new - end + delegate :config, :to => :instance def inherited(base) - raise "You cannot inherit from a Rails::Railtie child" + raise "You cannot inherit from a #{self.superclass.name} child" end - end - def config - self.class.config + def instance + @instance ||= new + end + + def respond_to?(*args) + super || instance.respond_to?(*args) + end + + def configure(&block) + class_eval(&block) + end + + protected + + def method_missing(*args, &block) + instance.send(*args, &block) + end end end end diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index 4e6f94c534..f09e3940cc 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -5,6 +5,7 @@ module Rails class Configuration def initialize @@options ||= {} + @@static_asset_paths = ActiveSupport::OrderedHash.new end # This allows you to modify the application's middlewares from Engines. @@ -65,6 +66,13 @@ module Rails super || @@options.key?(name.to_sym) end + # static_asset_paths is a Hash containing asset_paths + # with associated public folders, like: + # { "/" => "/app/public", "/my_engine" => "app/engines/my_engine/public" } + def static_asset_paths + @@static_asset_paths + end + private def method_missing(name, *args, &blk) @@ -78,4 +86,4 @@ module Rails end end end -end
\ No newline at end of file +end |