aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/rails/application.rb37
-rw-r--r--railties/lib/rails/configuration.rb4
-rw-r--r--railties/lib/rails/engine.rb84
-rw-r--r--railties/lib/rails/plugin.rb15
-rw-r--r--railties/lib/rails/railtie.rb171
-rw-r--r--railties/lib/rails/subscriber.rb17
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)