2016-08-06 13:15:47 -04:00
|
|
|
require "rails/initializable"
|
|
|
|
require "active_support/inflector"
|
|
|
|
require "active_support/core_ext/module/introspection"
|
|
|
|
require "active_support/core_ext/module/delegation"
|
2010-01-23 16:30:17 -05:00
|
|
|
|
2009-12-31 16:11:54 -05:00
|
|
|
module Rails
|
2016-04-11 15:26:57 -04:00
|
|
|
# <tt>Rails::Railtie</tt> is the core of the Rails framework and provides
|
|
|
|
# several hooks to extend Rails and/or modify the initialization process.
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# Every major component of Rails (Action Mailer, Action Controller, Active
|
|
|
|
# Record, etc.) implements a railtie. Each of them is responsible for their
|
|
|
|
# own initialization. This makes Rails itself absent of any component hooks,
|
|
|
|
# allowing other components to be used in place of any of the Rails defaults.
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# Developing a Rails extension does _not_ require implementing a railtie, but
|
|
|
|
# if you need to interact with the Rails framework during or after boot, then
|
|
|
|
# a railtie is needed.
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# For example, an extension doing any of the following would need a railtie:
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2010-02-02 14:05:26 -05:00
|
|
|
# * creating initializers
|
2011-02-19 01:20:04 -05:00
|
|
|
# * configuring a Rails framework for the application, like setting a generator
|
2013-12-26 05:14:38 -05:00
|
|
|
# * adding <tt>config.*</tt> keys to the environment
|
2016-04-11 15:26:57 -04:00
|
|
|
# * setting up a subscriber with <tt>ActiveSupport::Notifications</tt>
|
|
|
|
# * adding Rake tasks
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# == Creating a Railtie
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# To extend Rails using a railtie, create a subclass of <tt>Rails::Railtie</tt>.
|
|
|
|
# This class must be loaded during the Rails boot process, and is conventionally
|
|
|
|
# called <tt>MyNamespace::Railtie</tt>.
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# The following example demonstrates an extension which can be used with or
|
|
|
|
# without Rails.
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2011-02-19 01:20:04 -05:00
|
|
|
# # lib/my_gem/railtie.rb
|
|
|
|
# module MyGem
|
|
|
|
# class Railtie < Rails::Railtie
|
2010-01-21 22:54:32 -05:00
|
|
|
# end
|
2011-02-19 01:20:04 -05:00
|
|
|
# end
|
2010-06-21 06:07:13 -04:00
|
|
|
#
|
2011-02-19 01:20:04 -05:00
|
|
|
# # lib/my_gem.rb
|
|
|
|
# require 'my_gem/railtie' if defined?(Rails)
|
2010-01-21 22:54:32 -05:00
|
|
|
#
|
2010-02-02 14:05:26 -05:00
|
|
|
# == Initializers
|
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# To add an initialization step to the Rails boot process from your railtie, just
|
|
|
|
# define the initialization code with the +initializer+ macro:
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# class MyRailtie < Rails::Railtie
|
|
|
|
# initializer "my_railtie.configure_rails_initialization" do
|
|
|
|
# # some initialization behavior
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2010-06-21 06:07:13 -04:00
|
|
|
# If specified, the block can also receive the application object, in case you
|
2016-04-11 15:26:57 -04:00
|
|
|
# need to access some application-specific configuration, like middleware:
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# class MyRailtie < Rails::Railtie
|
|
|
|
# initializer "my_railtie.configure_rails_initialization" do |app|
|
2010-07-24 15:28:45 -04:00
|
|
|
# app.middleware.use MyRailtie::Middleware
|
2010-02-02 14:05:26 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# Finally, you can also pass <tt>:before</tt> and <tt>:after</tt> as options to
|
|
|
|
# +initializer+, in case you want to couple it with a specific step in the
|
|
|
|
# initialization process.
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# == Configuration
|
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# Railties can access a config object which contains configuration shared by all
|
|
|
|
# railties and the application:
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# class MyRailtie < Rails::Railtie
|
|
|
|
# # Customize the ORM
|
2010-10-02 12:38:23 -04:00
|
|
|
# config.app_generators.orm :my_railtie_orm
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# # Add a to_prepare block which is executed once in production
|
2016-04-11 15:26:57 -04:00
|
|
|
# # and before each request in development.
|
2010-02-02 14:05:26 -05:00
|
|
|
# config.to_prepare do
|
|
|
|
# MyRailtie.setup!
|
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# == Loading Rake Tasks and Generators
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# If your railtie has Rake tasks, you can tell Rails to load them through the method
|
|
|
|
# +rake_tasks+:
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
2010-11-16 10:26:21 -05:00
|
|
|
# class MyRailtie < Rails::Railtie
|
2010-02-02 14:05:26 -05:00
|
|
|
# rake_tasks do
|
2016-04-11 15:26:57 -04:00
|
|
|
# load 'path/to/my_railtie.tasks'
|
2010-02-02 14:05:26 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2015-01-13 22:26:49 -05:00
|
|
|
# By default, Rails loads generators from your load path. However, if you want to place
|
2016-04-11 15:26:57 -04:00
|
|
|
# your generators at a different location, you can specify in your railtie a block which
|
2010-02-02 14:05:26 -05:00
|
|
|
# will load them during normal generators lookup:
|
|
|
|
#
|
2010-11-16 10:26:21 -05:00
|
|
|
# class MyRailtie < Rails::Railtie
|
2010-02-02 14:05:26 -05:00
|
|
|
# generators do
|
2016-04-11 15:26:57 -04:00
|
|
|
# require 'path/to/my_railtie_generator'
|
2010-02-02 14:05:26 -05:00
|
|
|
# end
|
|
|
|
# end
|
|
|
|
#
|
2017-05-30 12:25:20 -04:00
|
|
|
# Since filenames on the load path are shared across gems, be sure that files you load
|
|
|
|
# through a railtie have unique names.
|
|
|
|
#
|
2012-01-02 15:49:18 -05:00
|
|
|
# == Application and Engine
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
2016-04-11 15:26:57 -04:00
|
|
|
# An engine is nothing more than a railtie with some initializers already set. And since
|
|
|
|
# <tt>Rails::Application</tt> is an engine, the same configuration described here can be
|
|
|
|
# used in both.
|
2010-02-02 14:05:26 -05:00
|
|
|
#
|
|
|
|
# Be sure to look at the documentation of those specific classes for more information.
|
2009-12-31 16:11:54 -05:00
|
|
|
class Railtie
|
2016-08-06 13:15:47 -04:00
|
|
|
autoload :Configuration, "rails/railtie/configuration"
|
2010-01-23 12:41:53 -05:00
|
|
|
|
2009-12-31 16:11:54 -05:00
|
|
|
include Initializable
|
|
|
|
|
2012-01-02 15:49:18 -05:00
|
|
|
ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application)
|
2009-12-31 16:11:54 -05:00
|
|
|
|
2010-01-21 17:14:20 -05:00
|
|
|
class << self
|
2010-07-19 11:53:14 -04:00
|
|
|
private :new
|
2013-03-18 22:12:35 -04:00
|
|
|
delegate :config, to: :instance
|
2010-07-19 11:53:14 -04:00
|
|
|
|
2010-01-23 12:41:53 -05:00
|
|
|
def subclasses
|
|
|
|
@subclasses ||= []
|
2010-01-21 17:14:20 -05:00
|
|
|
end
|
2009-12-31 16:11:54 -05:00
|
|
|
|
2010-01-21 17:14:20 -05:00
|
|
|
def inherited(base)
|
2010-03-26 09:41:40 -04:00
|
|
|
unless base.abstract_railtie?
|
2010-01-23 12:41:53 -05:00
|
|
|
subclasses << base
|
|
|
|
end
|
2010-01-21 17:14:20 -05:00
|
|
|
end
|
2009-12-31 16:11:54 -05:00
|
|
|
|
2010-01-21 17:14:20 -05:00
|
|
|
def rake_tasks(&blk)
|
2016-08-04 00:14:37 -04:00
|
|
|
register_block_for(:rake_tasks, &blk)
|
2010-01-21 17:14:20 -05:00
|
|
|
end
|
2009-12-31 16:11:54 -05:00
|
|
|
|
2010-07-17 04:59:41 -04:00
|
|
|
def console(&blk)
|
2016-08-04 00:14:37 -04:00
|
|
|
register_block_for(:load_console, &blk)
|
2010-07-17 04:59:41 -04:00
|
|
|
end
|
|
|
|
|
2012-05-29 10:31:27 -04:00
|
|
|
def runner(&blk)
|
2016-08-04 00:14:37 -04:00
|
|
|
register_block_for(:runner, &blk)
|
2012-05-29 10:31:27 -04:00
|
|
|
end
|
|
|
|
|
2010-01-21 17:14:20 -05:00
|
|
|
def generators(&blk)
|
2016-08-04 00:14:37 -04:00
|
|
|
register_block_for(:generators, &blk)
|
2010-01-21 17:14:20 -05:00
|
|
|
end
|
2010-01-23 12:41:53 -05:00
|
|
|
|
2010-03-26 09:41:40 -04:00
|
|
|
def abstract_railtie?
|
|
|
|
ABSTRACT_RAILTIES.include?(name)
|
2010-03-01 21:52:07 -05:00
|
|
|
end
|
2010-07-26 11:05:04 -04:00
|
|
|
|
|
|
|
def railtie_name(name = nil)
|
2010-07-26 13:33:58 -04:00
|
|
|
@railtie_name = name.to_s if name
|
2010-08-03 16:36:12 -04:00
|
|
|
@railtie_name ||= generate_railtie_name(self.name)
|
2010-07-26 11:05:04 -04:00
|
|
|
end
|
2010-08-03 16:36:12 -04:00
|
|
|
|
2013-03-18 22:12:35 -04:00
|
|
|
# Since Rails::Railtie cannot be instantiated, any methods that call
|
|
|
|
# +instance+ are intended to be called only on subclasses of a Railtie.
|
|
|
|
def instance
|
|
|
|
@instance ||= new
|
|
|
|
end
|
|
|
|
|
|
|
|
# Allows you to configure the railtie. This is the same method seen in
|
|
|
|
# Railtie::Configurable, but this module is no longer required for all
|
|
|
|
# subclasses of Railtie so we provide the class method here.
|
|
|
|
def configure(&block)
|
2013-04-30 12:26:55 -04:00
|
|
|
instance.configure(&block)
|
2013-03-18 22:12:35 -04:00
|
|
|
end
|
|
|
|
|
2016-12-23 05:20:01 -05:00
|
|
|
private
|
|
|
|
def generate_railtie_name(string)
|
2014-02-26 18:43:20 -05:00
|
|
|
ActiveSupport::Inflector.underscore(string).tr("/", "_")
|
2010-08-03 16:36:12 -04:00
|
|
|
end
|
2013-03-18 22:12:35 -04:00
|
|
|
|
2017-04-22 05:29:05 -04:00
|
|
|
def respond_to_missing?(name, _)
|
|
|
|
instance.respond_to?(name) || super
|
|
|
|
end
|
|
|
|
|
2013-03-18 22:12:35 -04:00
|
|
|
# If the class method does not have a method, then send the method call
|
|
|
|
# to the Railtie instance.
|
|
|
|
def method_missing(name, *args, &block)
|
|
|
|
if instance.respond_to?(name)
|
|
|
|
instance.public_send(name, *args, &block)
|
|
|
|
else
|
|
|
|
super
|
|
|
|
end
|
|
|
|
end
|
2016-11-01 19:24:07 -04:00
|
|
|
|
|
|
|
# receives an instance variable identifier, set the variable value if is
|
|
|
|
# blank and append given block to value, which will be used later in
|
|
|
|
# `#each_registered_block(type, &block)`
|
|
|
|
def register_block_for(type, &blk)
|
|
|
|
var_name = "@#{type}"
|
2016-11-01 21:17:22 -04:00
|
|
|
blocks = instance_variable_defined?(var_name) ? instance_variable_get(var_name) : instance_variable_set(var_name, [])
|
2016-11-01 19:24:07 -04:00
|
|
|
blocks << blk if blk
|
|
|
|
blocks
|
|
|
|
end
|
2010-01-19 12:43:09 -05:00
|
|
|
end
|
|
|
|
|
2013-01-06 04:43:30 -05:00
|
|
|
delegate :railtie_name, to: :class
|
2010-07-26 11:05:04 -04:00
|
|
|
|
2016-02-08 23:29:32 -05:00
|
|
|
def initialize #:nodoc:
|
2013-03-18 22:12:35 -04:00
|
|
|
if self.class.abstract_railtie?
|
|
|
|
raise "#{self.class.name} is abstract, you cannot instantiate it directly."
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-08 23:29:32 -05:00
|
|
|
def configure(&block) #:nodoc:
|
2013-04-30 12:26:55 -04:00
|
|
|
instance_eval(&block)
|
|
|
|
end
|
|
|
|
|
2016-02-08 23:29:32 -05:00
|
|
|
# This is used to create the <tt>config</tt> object on Railties, an instance of
|
|
|
|
# Railtie::Configuration, that is used by Railties and Application to store
|
|
|
|
# related configuration.
|
2010-07-19 11:53:14 -04:00
|
|
|
def config
|
|
|
|
@config ||= Railtie::Configuration.new
|
|
|
|
end
|
|
|
|
|
2016-02-08 23:29:32 -05:00
|
|
|
def railtie_namespace #:nodoc:
|
2012-06-29 10:50:51 -04:00
|
|
|
@railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) }
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
2016-08-06 13:55:02 -04:00
|
|
|
def run_console_blocks(app) #:nodoc:
|
|
|
|
each_registered_block(:console) { |block| block.call(app) }
|
|
|
|
end
|
2010-01-19 12:43:09 -05:00
|
|
|
|
2016-08-06 13:55:02 -04:00
|
|
|
def run_generators_blocks(app) #:nodoc:
|
|
|
|
each_registered_block(:generators) { |block| block.call(app) }
|
|
|
|
end
|
2012-06-29 10:50:51 -04:00
|
|
|
|
2016-08-06 13:55:02 -04:00
|
|
|
def run_runner_blocks(app) #:nodoc:
|
|
|
|
each_registered_block(:runner) { |block| block.call(app) }
|
|
|
|
end
|
2012-05-29 10:31:27 -04:00
|
|
|
|
2016-08-06 13:55:02 -04:00
|
|
|
def run_tasks_blocks(app) #:nodoc:
|
|
|
|
extend Rake::DSL
|
|
|
|
each_registered_block(:rake_tasks) { |block| instance_exec(app, &block) }
|
|
|
|
end
|
2010-10-09 14:11:36 -04:00
|
|
|
|
2014-04-04 08:05:29 -04:00
|
|
|
private
|
2012-06-29 10:50:51 -04:00
|
|
|
|
2016-11-01 12:36:00 -04:00
|
|
|
# run `&block` in every registered block in `#register_block_for`
|
2016-08-06 13:55:02 -04:00
|
|
|
def each_registered_block(type, &block)
|
|
|
|
klass = self.class
|
|
|
|
while klass.respond_to?(type)
|
|
|
|
klass.public_send(type).each(&block)
|
|
|
|
klass = klass.superclass
|
|
|
|
end
|
2010-10-09 14:11:36 -04:00
|
|
|
end
|
2009-12-31 16:11:54 -05:00
|
|
|
end
|
|
|
|
end
|