diff options
Diffstat (limited to 'railties/lib')
-rw-r--r-- | railties/lib/rails/application.rb | 37 | ||||
-rw-r--r-- | railties/lib/rails/configuration.rb | 4 | ||||
-rw-r--r-- | railties/lib/rails/engine.rb | 84 | ||||
-rw-r--r-- | railties/lib/rails/plugin.rb | 15 | ||||
-rw-r--r-- | railties/lib/rails/railtie.rb | 171 | ||||
-rw-r--r-- | railties/lib/rails/subscriber.rb | 17 |
6 files changed, 319 insertions, 9 deletions
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 9384492486..f445ef4831 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -4,6 +4,43 @@ require 'rails/plugin' require 'rails/engine' module Rails + # In Rails 3.0, a Rails::Application object was introduced which is nothing more than + # an Engine but with the responsibility of coordinating the whole boot process. + # + # Opposite to Rails::Engine, you can only have one Rails::Application instance + # in your process and both Rails::Application and YourApplication::Application + # points to it. + # + # In other words, Rails::Application is Singleton and whenever you are accessing + # Rails::Application.config or YourApplication::Application.config, you are actually + # accessing YourApplication::Application.instance.config. + # + # == Initialization + # + # Rails::Application is responsible for executing all railties, engines and plugin + # initializers. Besides, it also executed some bootstrap initializers (check + # Rails::Application::Bootstrap) and finishing initializers, after all the others + # are executed (check Rails::Application::Finisher). + # + # == Configuration + # + # Besides providing the same configuration as Rails::Engine and Rails::Railtie, + # the application object has several specific configurations, for example + # "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters", + # "logger", "metals", "reload_engines", "reload_plugins" and so forth. + # + # Check Rails::Application::Configuration to see them all. + # + # == Routes + # + # The application object is also responsible for holding the routes and reloading routes + # whenever the files change in development. + # + # == Middlewares and metals + # + # The Application is also responsible for building the middleware stack and setting up + # both application and engines metals. + # class Application < Engine autoload :Bootstrap, 'rails/application/bootstrap' autoload :Configurable, 'rails/application/configurable' diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 7887a5d25f..80b72252f1 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -4,6 +4,7 @@ require 'rails/rack' module Rails module Configuration + # Holds coonfiguration shared between Railtie, Engine and Application. module Shared def middleware @@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware| @@ -87,6 +88,8 @@ module Rails end end + # Generators configuration which uses method missing to wrap it in a nifty DSL. + # It also allows you to set generators fallbacks and aliases. class Generators #:nodoc: attr_accessor :aliases, :options, :fallbacks, :colorize_logging @@ -119,6 +122,7 @@ module Rails end end + # Holds configs deprecated in 3.0. Will be removed on 3.1. module Deprecated def frameworks(*args) raise "config.frameworks in no longer supported. See the generated " \ diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 33d62c8155..096bb9b934 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -2,6 +2,90 @@ require 'active_support/core_ext/module/delegation' require 'rails/railtie' module Rails + # Rails::Engine allows you to wrap a specific Rails application and share it accross + # different applications. Since Rails 3.0, your Rails::Application is nothing + # more than an Engine, thus your engines will behave much more closer to an application + # since then. + # + # Any Rails::Engine is also a Rails::Railtie, so the same methods (like rake_tasks and + # generators) and configuration available in the latter can also be used in the former. + # + # == Creating an Engine + # + # In Rails versions before to 3.0, your gems automatically behaved as Engine, however + # this coupled Rails to Rubygems. Since Rails 3.0, if you want a gem to automatically + # behave as Engine, you have to specify an Engine for it somewhere inside your plugin + # lib folder (similar with how we spceify a Railtie): + # + # # lib/my_engine.rb + # module MyEngine + # class Engine < Rails::Engine + # engine_name :my_engine + # end + # end + # + # Then ensure that this file is loaded at the top of your config/application.rb (or in + # your Gemfile) and it will automatically load models, controllers, helpers and metals + # inside app, load routes at "config/routes.rb", load locales at "config/locales/*", + # load tasks at "lib/tasks/*". + # + # == Configuration + # + # Besides the Railtie configuration which is shared across the application, in a + # Rails::Engine you can access load_paths, eager_load_paths and load_once_paths, + # which differently from a Railtie, are scoped to the current Engine. + # + # Example: + # + # class MyEngine < Rails::Engine + # # config.middleware is shared configururation + # config.middleware.use MyEngine::Middleware + # + # # Add a load path for this specific Engine + # config.load_paths << File.expand_path("../lib/some/path", __FILE__) + # end + # + # == Paths + # + # Since Rails 3.0, both your Application and Engines does not have hardcoded paths. + # This means that you are not required to place your controllers at "app/controllers", + # but in any place which you find convenient. + # + # For example, let's suppose you want to lay your controllers at lib/controllers, all + # you need to do is: + # + # class MyEngine < Rails::Engine + # paths.app.controllers = "lib/controllers" + # end + # + # You can also have your controllers being loaded from both "app/controllers" and + # "lib/controllers": + # + # class MyEngine < Rails::Engine + # paths.app.controllers << "lib/controllers" + # end + # + # The available paths in an Engine are: + # + # class MyEngine < Rails::Engine + # paths.app = "app" + # paths.app.controllers = "app/controllers" + # paths.app.helpers = "app/helpers" + # paths.app.models = "app/models" + # paths.app.metals = "app/metal" + # paths.app.views = "app/views" + # paths.lib = "lib" + # paths.lib.tasks = "lib/tasks" + # paths.config = "config" + # paths.config.initializers = "config/initializers" + # paths.config.locales = "config/locales" + # paths.config.routes = "config/routes.rb" + # end + # + # Your Application class adds a couple more paths to this set. And as in your Application, + # all folders under "app" are automatically added to the load path. So if you have + # "app/observers", it's added by default. + # class Engine < Railtie autoload :Configurable, "rails/engine/configurable" autoload :Configuration, "rails/engine/configuration" diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 64d03e7599..2a746e0fa6 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -1,6 +1,21 @@ require 'rails/engine' module Rails + # Rails::Plugin is nothing more than a Rails::Engine, but since it's loaded too late + # in the boot process, it does not have the same configuration powers as a bare + # Rails::Engine. + # + # Opposite to Rails::Railtie and Rails::Engine, you are not supposed to inherit from + # Rails::Plugin. Rails::Plugin is automatically configured to be an engine by simply + # placing inside vendor/plugins. Since this is done automatically, you actually cannot + # declare a Rails::Engine inside your Plugin, otherwise it would cause the same files + # to be loaded twice. This means that if you want to ship an Engine as gem it cannot + # be used as plugin and vice-versa. + # + # Besides this conceptual difference, the only difference between Rails::Engine and + # Rails::Plugin is that plugins automatically load the file "init.rb" at the plugin + # root during the boot process. + # class Plugin < Engine def self.inherited(base) raise "You cannot inherit from Rails::Plugin" diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb index c038d0ac70..7bb932031c 100644 --- a/railties/lib/rails/railtie.rb +++ b/railties/lib/rails/railtie.rb @@ -2,6 +2,177 @@ require 'rails/initializable' require 'rails/configuration' module Rails + # Railtie is the core of the Rails Framework and provides several hooks to extend + # Rails and/or modify the initialization process. + # + # Every major component of Rails (Action Mailer, Action Controller, + # Action View, Active Record and Active Resource) are all Railties, so each of + # them is responsible to set their own initialization. This makes, for example, + # Rails absent of any ActiveRecord hook, allowing any other ORM to hook in. + # + # Developing a Rails extension does not _require_ any implementation of + # Railtie, but if you need to interact with the Rails framework + # during boot, or after boot, then Railtie is what you need to do that + # interaction. + # + # For example, the following would need you to implement Railtie in your + # plugin: + # + # * creating initializers + # * configuring a Rails framework or the Application, like setting a generator + # * adding Rails config.* keys to the environment + # * setting up a subscriber to the Rails +ActiveSupport::Notifications+ + # * adding rake tasks into rails + # + # == Creating your Railtie + # + # Implementing Railtie in your Rails extension is done by creating a class + # Railtie that has your extension name and making sure that this gets loaded + # during boot time of the Rails stack. + # + # You can do this however you wish, but here is an example if you want to provide + # it for a gem that can be used with or without Rails: + # + # * Create a file (say, lib/my_gem/railtie.rb) which contains class Railtie inheriting from + # Rails::Railtie and is namespaced to your gem: + # + # # lib/my_gem/railtie.rb + # module MyGem + # class Railtie < Rails::Railtie + # railtie_name :mygem + # end + # end + # + # * Require your own gem as well as rails in this file: + # + # # lib/my_gem/railtie.rb + # require 'my_gem' + # require 'rails' + # + # module MyGem + # class Railtie < Rails::Railtie + # railtie_name :mygem + # end + # end + # + # * Make sure your Gem loads the railtie.rb file if Rails is loaded first, an easy + # way to check is by checking for the Rails constant which will exist if Rails + # has started: + # + # # lib/my_gem.rb + # module MyGem + # require 'lib/my_gem/railtie' if defined?(Rails) + # end + # + # * Or instead of doing the require automatically, you can ask your users to require + # it for you in their Gemfile: + # + # # #{USER_RAILS_ROOT}/Gemfile + # gem "my_gem", :require_as => ["my_gem", "my_gem/railtie"] + # + # == Initializers + # + # To add an initialization step from your Railtie to Rails boot process, you just need + # to create an initializer block: + # + # class MyRailtie < Rails::Railtie + # initializer "my_railtie.configure_rails_initialization" do + # # some initialization behavior + # end + # end + # + # If specified, the block can also receive the application object, in case you + # need to access some application specific configuration: + # + # class MyRailtie < Rails::Railtie + # initializer "my_railtie.configure_rails_initialization" do |app| + # if app.config.cache_classes + # # some initialization behavior + # end + # end + # end + # + # Finally, you can also pass :before and :after as option to initializer, in case + # you want to couple it with a specific step in the initialization process. + # + # == Configuration + # + # Inside the Railtie class, you can access a config object which contains configuration + # shared by all railties and the application: + # + # class MyRailtie < Rails::Railtie + # # Customize the ORM + # config.generators.orm :my_railtie_orm + # + # # Add a middleware + # config.middlewares.use MyRailtie::Middleware + # + # # Add a to_prepare block which is executed once in production + # # and before which request in development + # config.to_prepare do + # MyRailtie.setup! + # end + # end + # + # == Loading rake tasks and generators + # + # If your railtie has rake tasks, you can tell Rails to load them through the method + # rake tasks: + # + # class MyRailtie < Railtie + # rake_tasks do + # load "path/to/my_railtie.tasks" + # end + # end + # + # By default, Rails load generators from your load path. However, if you want to place + # your generators at a different location, you can specify in your Railtie a block which + # will load them during normal generators lookup: + # + # class MyRailtie < Railtie + # generators do + # require "path/to/my_railtie_generator" + # end + # end + # + # == Adding your subscriber + # + # Since version 3.0, Rails ships with a notification system which is used for several + # purposes, including logging. If you are sending notifications in your Railtie, you may + # want to add a subscriber to consume such notifications for logging purposes. + # + # The subscriber is added under the railtie_name namespace and only consumes notifications + # under the given namespace. For example, let's suppose your railtie is publishing the + # following "something_expensive" instrumentation: + # + # ActiveSupport::Notifications.instrument "my_railtie.something_expensive" do + # # something expensive + # end + # + # You can log this instrumentation with your own Rails::Subscriber: + # + # class MyRailtie::Subscriber < Rails::Subscriber + # def something_expensive(event) + # info("Something expensive took %.1fms" % event.duration) + # end + # end + # + # By registering it: + # + # class MyRailtie < Railtie + # subscriber MyRailtie::Subscriber.new + # end + # + # Take a look in Rails::Subscriber docs for more information. + # + # == Application, Plugin and Engine + # + # A Rails::Engine is nothing more than a Railtie with some initializers already set. + # And since Rails::Application and Rails::Plugin are engines, the same configuration + # described here can be used in all three. + # + # Be sure to look at the documentation of those specific classes for more information. + # class Railtie autoload :Configurable, "rails/railtie/configurable" autoload :Configuration, "rails/railtie/configuration" diff --git a/railties/lib/rails/subscriber.rb b/railties/lib/rails/subscriber.rb index 8c62f562d9..9bf22f27a4 100644 --- a/railties/lib/rails/subscriber.rb +++ b/railties/lib/rails/subscriber.rb @@ -3,10 +3,10 @@ require 'active_support/notifications' module Rails # Rails::Subscriber is an object set to consume ActiveSupport::Notifications - # on initialization with solely purpose of logging. The subscriber dispatches - # notifications to a regirested object based on its given namespace. + # on initialization with the sole purpose of logging. The subscriber dispatches + # notifications to a registered object based on it's given namespace. # - # An example would be ActiveRecord subscriber responsible for logging queries: + # An example would be an Active Record subscriber responsible for logging queries: # # module ActiveRecord # class Railtie @@ -18,20 +18,20 @@ module Rails # end # end # - # It's finally registed as: + # Which would be registed as: # # Rails::Subscriber.add :active_record, ActiveRecord::Railtie::Subscriber.new # - # So whenever a "active_record.sql" notification arrive to Rails::Subscriber, + # So whenever an +active_record.sql+ notification arrives to Rails::Subscriber, # it will properly dispatch the event (ActiveSupport::Notifications::Event) to # the sql method. # - # This is useful because it avoids spanning several subscribers just for logging - # purposes(which slows down the main thread). Besides of providing a centralized + # This avoids spanning several subscribers just for logging purposes + # (which slows down the main thread). It also provides a centralized # facility on top of Rails.logger. # # Subscriber also has some helpers to deal with logging and automatically flushes - # all logs when the request finishes (via action_dispatch.callback notification). + # all logs when the request finishes. class Subscriber mattr_accessor :colorize_logging self.colorize_logging = true @@ -97,7 +97,6 @@ module Rails # option is set to true, it also adds bold to the string. This is based # on Highline implementation and it automatically appends CLEAR to the end # of the returned String. - # def color(text, color, bold=false) return text unless colorize_logging color = self.class.const_get(color.to_s.upcase) if color.is_a?(Symbol) |