mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add docs for Railtie, Engine, Plugin and Application.
This commit is contained in:
parent
12f595b130
commit
781d0a9bae
6 changed files with 265 additions and 62 deletions
|
@ -4,6 +4,43 @@ require 'rails/plugin'
|
||||||
require 'rails/engine'
|
require 'rails/engine'
|
||||||
|
|
||||||
module Rails
|
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
|
class Application < Engine
|
||||||
autoload :Bootstrap, 'rails/application/bootstrap'
|
autoload :Bootstrap, 'rails/application/bootstrap'
|
||||||
autoload :Configurable, 'rails/application/configurable'
|
autoload :Configurable, 'rails/application/configurable'
|
||||||
|
|
|
@ -4,6 +4,7 @@ require 'rails/rack'
|
||||||
|
|
||||||
module Rails
|
module Rails
|
||||||
module Configuration
|
module Configuration
|
||||||
|
# Holds coonfiguration shared between Railtie, Engine and Application.
|
||||||
module Shared
|
module Shared
|
||||||
def middleware
|
def middleware
|
||||||
@@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware|
|
@@default_middleware_stack ||= ActionDispatch::MiddlewareStack.new.tap do |middleware|
|
||||||
|
@ -87,6 +88,8 @@ module Rails
|
||||||
end
|
end
|
||||||
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:
|
class Generators #:nodoc:
|
||||||
attr_accessor :aliases, :options, :fallbacks, :colorize_logging
|
attr_accessor :aliases, :options, :fallbacks, :colorize_logging
|
||||||
|
|
||||||
|
@ -119,6 +122,7 @@ module Rails
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Holds configs deprecated in 3.0. Will be removed on 3.1.
|
||||||
module Deprecated
|
module Deprecated
|
||||||
def frameworks(*args)
|
def frameworks(*args)
|
||||||
raise "config.frameworks in no longer supported. See the generated " \
|
raise "config.frameworks in no longer supported. See the generated " \
|
||||||
|
|
|
@ -2,6 +2,90 @@ require 'active_support/core_ext/module/delegation'
|
||||||
require 'rails/railtie'
|
require 'rails/railtie'
|
||||||
|
|
||||||
module Rails
|
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
|
class Engine < Railtie
|
||||||
autoload :Configurable, "rails/engine/configurable"
|
autoload :Configurable, "rails/engine/configurable"
|
||||||
autoload :Configuration, "rails/engine/configuration"
|
autoload :Configuration, "rails/engine/configuration"
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
require 'rails/engine'
|
require 'rails/engine'
|
||||||
|
|
||||||
module Rails
|
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
|
class Plugin < Engine
|
||||||
def self.inherited(base)
|
def self.inherited(base)
|
||||||
raise "You cannot inherit from Rails::Plugin"
|
raise "You cannot inherit from Rails::Plugin"
|
||||||
|
|
|
@ -2,66 +2,36 @@ require 'rails/initializable'
|
||||||
require 'rails/configuration'
|
require 'rails/configuration'
|
||||||
|
|
||||||
module Rails
|
module Rails
|
||||||
# Railtie is the core of the Rails Framework and provides all the hooks and
|
# Railtie is the core of the Rails Framework and provides several hooks to extend
|
||||||
# methods you need to link your plugin into Rails.
|
# Rails and/or modify the initialization process.
|
||||||
#
|
#
|
||||||
# What Railtie does is make every component of Rails a "plugin" and creates
|
# Every major component of Rails (Action Mailer, Action Controller,
|
||||||
# an API that exposes all the powers that the builtin components need
|
# Action View, Active Record and Active Resource) are all Railties, so each of
|
||||||
# to any plugin author.
|
# 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.
|
||||||
#
|
#
|
||||||
# In fact, every major component of Rails (Action Mailer, Action Controller,
|
# Developing a Rails extension does not _require_ any implementation of
|
||||||
# Action View, Active Record and Active Resource) are all now just plain
|
# Railtie, but if you need to interact with the Rails framework
|
||||||
# old plugins, so anything they can do, your plugin can do.
|
|
||||||
#
|
|
||||||
# Developing a plugin for Rails does not _require_ any implementation of
|
|
||||||
# Railtie, there is no fixed rule, but as a guideline, if your plugin works
|
|
||||||
# by just being required before Rails boots, then there is no need for you
|
|
||||||
# to hook into 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
|
# during boot, or after boot, then Railtie is what you need to do that
|
||||||
# interaction.
|
# interaction.
|
||||||
#
|
#
|
||||||
# For example, the following would need you to implement Railtie in your
|
# For example, the following would need you to implement Railtie in your
|
||||||
# plugin:
|
# plugin:
|
||||||
#
|
#
|
||||||
# * creating initializers (including route insertion)
|
# * creating initializers
|
||||||
# * modifying the render path (think HAML et al)
|
# * configuring a Rails framework or the Application, like setting a generator
|
||||||
# * adding Rails config.* keys to the environment
|
# * adding Rails config.* keys to the environment
|
||||||
# * setting up a subscriber to the Rails +ActiveSupport::Notifications+
|
# * setting up a subscriber to the Rails +ActiveSupport::Notifications+
|
||||||
# * adding global Rake tasks into rails
|
# * adding rake tasks into rails
|
||||||
# * setting up a default configuration for the Application
|
|
||||||
#
|
#
|
||||||
# Railtie gives you a central place to connect into the Rails framework. If you
|
# == Creating your Railtie
|
||||||
# find yourself writing plugin code that is having to monkey patch parts of the
|
|
||||||
# Rails framework to achieve something, there is probably a better, more elegant
|
|
||||||
# way to do it through Railtie, if there isn't, then you have found a lacking
|
|
||||||
# feature of Railtie, please lodge a ticket.
|
|
||||||
#
|
#
|
||||||
# Implementing Railtie in your plugin is by creating a class Railtie in your
|
# Implementing Railtie in your Rails extension is done by creating a class
|
||||||
# application that has your plugin name and making sure that this gets loaded
|
# Railtie that has your extension name and making sure that this gets loaded
|
||||||
# durng boot time of the Rails stack.
|
# during boot time of the Rails stack.
|
||||||
#
|
#
|
||||||
# You can do this however you wish, but three straight forward ways are:
|
# 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:
|
||||||
# == For gems or plugins that are not used outside of Rails
|
|
||||||
#
|
|
||||||
# * Create a Railtie subclass within your lib/my_plugin.rb file:
|
|
||||||
#
|
|
||||||
# # lib/my_plugin.rb
|
|
||||||
# module MyPlugin
|
|
||||||
# class Railtie < Rails::Railtie
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# * Pass in your plugin name
|
|
||||||
#
|
|
||||||
# # lib/my_plugin.rb
|
|
||||||
# module MyPlugin
|
|
||||||
# class Railtie < Rails::Railtie
|
|
||||||
# plugin_name :my_plugin
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# == For gems that could be used without Rails
|
|
||||||
#
|
#
|
||||||
# * Create a file (say, lib/my_gem/railtie.rb) which contains class Railtie inheriting from
|
# * Create a file (say, lib/my_gem/railtie.rb) which contains class Railtie inheriting from
|
||||||
# Rails::Railtie and is namespaced to your gem:
|
# Rails::Railtie and is namespaced to your gem:
|
||||||
|
@ -69,6 +39,7 @@ module Rails
|
||||||
# # lib/my_gem/railtie.rb
|
# # lib/my_gem/railtie.rb
|
||||||
# module MyGem
|
# module MyGem
|
||||||
# class Railtie < Rails::Railtie
|
# class Railtie < Rails::Railtie
|
||||||
|
# railtie_name :mygem
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
|
@ -80,18 +51,7 @@ module Rails
|
||||||
#
|
#
|
||||||
# module MyGem
|
# module MyGem
|
||||||
# class Railtie < Rails::Railtie
|
# class Railtie < Rails::Railtie
|
||||||
# end
|
# railtie_name :mygem
|
||||||
# end
|
|
||||||
#
|
|
||||||
# * Give your gem a unique name:
|
|
||||||
#
|
|
||||||
# # lib/my_gem/railtie.rb
|
|
||||||
# require 'my_gem'
|
|
||||||
# require 'rails'
|
|
||||||
#
|
|
||||||
# module MyGem
|
|
||||||
# class Railtie < Rails::Railtie
|
|
||||||
# plugin_name :my_gem
|
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
|
@ -101,7 +61,7 @@ module Rails
|
||||||
#
|
#
|
||||||
# # lib/my_gem.rb
|
# # lib/my_gem.rb
|
||||||
# module MyGem
|
# module MyGem
|
||||||
# require 'lib/railtie' if defined?(Rails)
|
# require 'lib/my_gem/railtie' if defined?(Rails)
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# * Or instead of doing the require automatically, you can ask your users to require
|
# * Or instead of doing the require automatically, you can ask your users to require
|
||||||
|
@ -110,6 +70,109 @@ module Rails
|
||||||
# # #{USER_RAILS_ROOT}/Gemfile
|
# # #{USER_RAILS_ROOT}/Gemfile
|
||||||
# gem "my_gem", :require_as => ["my_gem", "my_gem/railtie"]
|
# 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
|
class Railtie
|
||||||
autoload :Configurable, "rails/railtie/configurable"
|
autoload :Configurable, "rails/railtie/configurable"
|
||||||
autoload :Configuration, "rails/railtie/configuration"
|
autoload :Configuration, "rails/railtie/configuration"
|
||||||
|
|
|
@ -31,7 +31,7 @@ module Rails
|
||||||
# facility on top of Rails.logger.
|
# facility on top of Rails.logger.
|
||||||
#
|
#
|
||||||
# Subscriber also has some helpers to deal with logging and automatically flushes
|
# 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
|
class Subscriber
|
||||||
mattr_accessor :colorize_logging
|
mattr_accessor :colorize_logging
|
||||||
self.colorize_logging = true
|
self.colorize_logging = true
|
||||||
|
|
Loading…
Reference in a new issue