2018-07-23 22:29:31 -04:00
**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON https://guides.rubyonrails.org.**
2014-12-23 17:32:50 -05:00
2012-09-01 17:25:58 -04:00
The Rails Initialization Process
================================
2010-03-27 21:02:59 -04:00
2016-02-26 05:22:21 -05:00
This guide explains the internals of the initialization process in Rails.
It is an extremely in-depth guide and recommended for advanced Rails developers.
2010-03-27 21:02:59 -04:00
2012-11-29 17:25:02 -05:00
After reading this guide, you will know:
2020-03-21 17:37:54 -04:00
* How to use `bin/rails server` .
2013-06-28 03:41:30 -04:00
* The timeline of Rails' initialization sequence.
* Where different files are required by the boot sequence.
* How the Rails::Server interface is defined and used.
2010-03-27 21:02:59 -04:00
2012-09-01 17:25:58 -04:00
--------------------------------------------------------------------------------
2010-03-27 21:02:59 -04:00
2012-06-10 20:55:12 -04:00
This guide goes through every method call that is
2016-07-06 09:57:24 -04:00
required to boot up the Ruby on Rails stack for a default Rails
2012-06-17 14:11:22 -04:00
application, explaining each part in detail along the way. For this
2019-01-22 03:53:47 -05:00
guide, we will be focusing on what happens when you execute `bin/rails server`
2013-06-28 03:41:30 -04:00
to boot your app.
2010-12-14 23:08:08 -05:00
NOTE: Paths in this guide are relative to Rails or a Rails application unless otherwise specified.
2010-03-27 21:02:59 -04:00
2012-09-03 21:21:24 -04:00
TIP: If you want to follow along while browsing the Rails [source
code](https://github.com/rails/rails), we recommend that you use the `t`
2012-08-11 02:19:51 -04:00
key binding to open the file finder inside GitHub and find files
2012-06-17 14:14:19 -04:00
quickly.
2012-09-01 17:25:58 -04:00
Launch!
-------
2010-03-27 21:02:59 -04:00
2013-11-06 07:54:22 -05:00
Let's start to boot and initialize the app. A Rails application is usually
2020-03-21 17:37:54 -04:00
started by running `bin/rails console` or `bin/rails server` .
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
### `bin/rails`
2010-12-14 23:08:08 -05:00
2011-11-19 21:36:50 -05:00
This file is as follows:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2013-01-06 18:13:47 -05:00
#!/usr/bin/env ruby
2016-12-20 14:13:22 -05:00
APP_PATH = File.expand_path('../config/application', __dir__ )
2020-03-29 19:30:52 -04:00
require_relative "../config/boot"
require "rails/commands"
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
The `APP_PATH` constant will be used later in `rails/commands` . The `config/boot` file referenced here is the `config/boot.rb` file in our application which is responsible for loading Bundler and setting it up.
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `config/boot.rb`
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
`config/boot.rb` contains:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2016-12-20 14:13:22 -05:00
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__ )
2012-05-22 11:48:46 -04:00
2020-03-29 19:30:52 -04:00
require "bundler/setup" # Set up gems listed in the Gemfile.
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
In a standard Rails application, there's a `Gemfile` which declares all
dependencies of the application. `config/boot.rb` sets
2017-11-30 01:25:50 -05:00
`ENV['BUNDLE_GEMFILE']` to the location of this file. If the `Gemfile`
2013-06-28 03:41:30 -04:00
exists, then `bundler/setup` is required. The require is used by Bundler to
configure the load path for your Gemfile's dependencies.
2012-05-22 11:48:46 -04:00
2013-04-18 22:00:47 -04:00
A standard Rails application depends on several gems, specifically:
2017-08-19 20:41:37 -04:00
* actioncable
2013-04-18 22:00:47 -04:00
* actionmailer
* actionpack
2014-06-29 14:14:40 -04:00
* actionview
2017-08-19 20:41:37 -04:00
* activejob
2013-04-18 22:00:47 -04:00
* activemodel
* activerecord
2017-08-19 20:41:37 -04:00
* activestorage
2013-04-18 22:00:47 -04:00
* activesupport
2019-06-25 17:37:50 -04:00
* actionmailbox
* actiontext
2013-04-18 22:00:47 -04:00
* arel
* builder
* bundler
2017-07-16 10:29:23 -04:00
* erubi
2013-04-18 22:00:47 -04:00
* i18n
* mail
* mime-types
* rack
* rack-test
* rails
* railties
* rake
2014-06-29 14:14:40 -04:00
* sqlite3
2013-04-18 22:00:47 -04:00
* thor
* tzinfo
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `rails/commands.rb`
2010-12-14 23:08:08 -05:00
2013-11-08 04:43:59 -05:00
Once `config/boot.rb` has finished, the next file that is required is
`rails/commands` , which helps in expanding aliases. In the current case, the
2013-11-24 13:55:46 -05:00
`ARGV` array simply contains `server` which will be passed over:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
require "rails/command"
2012-05-22 11:55:59 -04:00
2011-06-04 15:28:21 -04:00
aliases = {
"g" => "generate",
2012-05-26 16:09:54 -04:00
"d" => "destroy",
2011-06-04 15:28:21 -04:00
"c" => "console",
"s" => "server",
2011-08-14 10:45:22 -04:00
"db" => "dbconsole",
2015-11-13 19:58:51 -05:00
"r" => "runner",
"t" => "test"
2011-06-04 15:28:21 -04:00
}
2010-12-14 23:08:08 -05:00
2011-06-04 15:28:21 -04:00
command = ARGV.shift
command = aliases[command] || command
2013-11-08 04:37:38 -05:00
2016-12-20 14:13:22 -05:00
Rails::Command.invoke command, ARGV
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2013-11-08 04:43:59 -05:00
If we had used `s` rather than `server` , Rails would have used the `aliases`
defined here to find the matching command.
2013-11-08 04:37:38 -05:00
2016-12-20 14:13:22 -05:00
### `rails/command.rb`
2013-11-08 04:43:59 -05:00
2016-12-20 14:13:22 -05:00
When one types a Rails command, `invoke` tries to lookup a command for the given
2017-06-28 12:54:18 -04:00
namespace and executes the command if found.
2010-12-14 23:08:08 -05:00
2016-12-20 14:13:22 -05:00
If Rails doesn't recognize the command, it hands the reins over to Rake
to run a task of the same name.
2013-11-08 04:43:59 -05:00
2019-06-10 02:46:24 -04:00
As shown, `Rails::Command` displays the help output automatically if the `namespace`
is empty.
2015-11-13 19:58:51 -05:00
2016-12-20 14:13:22 -05:00
```ruby
2019-08-25 08:55:50 -04:00
module Rails
module Command
class < < self
def invoke(full_namespace, args = [], **config)
namespace = full_namespace = full_namespace.to_s
if char = namespace =~ /:(\w+)$/
command_name, namespace = $1, namespace.slice(0, char)
else
command_name = namespace
end
command_name, namespace = "help", "help" if command_name.blank? || HELP_MAPPINGS.include?(command_name)
command_name, namespace = "version", "version" if %w( -v --version ).include?(command_name)
command = find_by_namespace(namespace, command_name)
if command & & command.all_commands[command_name]
command.perform(command_name, args, config)
else
find_by_namespace("rake").perform(full_namespace, args, config)
end
2016-12-20 14:13:22 -05:00
end
end
2013-11-08 04:43:59 -05:00
end
end
```
With the `server` command, Rails will further run the following code:
```ruby
2016-12-20 14:13:22 -05:00
module Rails
module Command
class ServerCommand < Base # :nodoc:
def perform
2019-08-25 08:55:50 -04:00
extract_environment_option_from_argument
2016-12-20 14:13:22 -05:00
set_application_directory!
2019-08-25 08:55:50 -04:00
prepare_restart
2017-08-19 20:41:37 -04:00
2019-08-25 08:55:50 -04:00
Rails::Server.new(server_options).tap do |server|
2016-12-20 14:13:22 -05:00
# Require application after server sets environment to propagate
# the --environment option.
require APP_PATH
Dir.chdir(Rails.application.root)
2019-08-25 08:55:50 -04:00
if server.serveable?
print_boot_information(server.server, server.served_url)
after_stop_callback = -> { say "Exiting" unless options[:daemon] }
server.start(after_stop_callback)
else
say rack_server_suggestion(using)
end
2016-12-20 14:13:22 -05:00
end
end
end
2013-01-05 17:57:03 -05:00
end
2013-11-08 04:43:59 -05:00
end
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2013-11-08 04:43:59 -05:00
This file will change into the Rails root directory (a path two directories up
from `APP_PATH` which points at `config/application.rb` ), but only if the
2016-12-20 14:13:22 -05:00
`config.ru` file isn't found. This then starts up the `Rails::Server` class.
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `actionpack/lib/action_dispatch.rb`
2010-12-14 23:08:08 -05:00
2012-06-17 14:30:20 -04:00
Action Dispatch is the routing component of the Rails framework.
2013-04-18 22:09:10 -04:00
It adds functionality like routing, session, and common middlewares.
2010-12-14 23:08:08 -05:00
2016-12-20 14:13:22 -05:00
### `rails/commands/server/server_command.rb`
2010-12-14 23:08:08 -05:00
2016-12-20 14:13:22 -05:00
The `Rails::Server` class is defined in this file by inheriting from
`Rack::Server` . When `Rails::Server.new` is called, this calls the `initialize`
method in `rails/commands/server/server_command.rb` :
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rails
class Server < ::Rack::Server
def initialize(options = nil)
@default_options = options || {}
super(@default_options)
set_environment
end
end
2011-06-04 15:28:21 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
Firstly, `super` is called which calls the `initialize` method on `Rack::Server` .
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
### Rack: `lib/rack/server.rb`
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
`Rack::Server` is responsible for providing a common server interface for all Rack-based applications, which Rails is now a part of.
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
The `initialize` method in `Rack::Server` simply sets several variables:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
def initialize(options = nil)
@ignore_options = []
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
if options
@use_default_options = false
@options = options
@app = options[:app] if options[:app]
else
argv = defined?(SPEC_ARGV) ? SPEC_ARGV : ARGV
@use_default_options = true
@options = parse_options(argv)
end
end
end
2011-06-04 15:28:21 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
In this case, return value of `Rails::Command::ServerCommand#server_options` will be assigned to `options` .
When lines inside if statement is evaluated, a couple of instance variables will be set.
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
`server_options` method in `Rails::Command::ServerCommand` is defined as follows:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rails
module Command
class ServerCommand
no_commands do
def server_options
{
user_supplied_options: user_supplied_options,
server: using,
log_stdout: log_to_stdout?,
Port: port,
Host: host,
DoNotReverseLookup: true,
config: options[:config],
environment: environment,
daemonize: options[:daemon],
pid: pid,
caching: options[:dev_caching],
restart_cmd: restart_command,
early_hints: early_hints
}
end
end
end
end
2011-06-04 15:28:21 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
The value will be assigned to instance variable `@options` .
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
After `super` has finished in `Rack::Server` , we jump back to
`rails/commands/server/server_command.rb` . At this point, `set_environment`
is called within the context of the `Rails::Server` object.
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rails
module Server
def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end
end
2016-12-20 14:13:22 -05:00
end
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
After `initialize` has finished, we jump back into the server command
where `APP_PATH` (which was set earlier) is required.
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `config/application`
2012-06-10 21:26:54 -04:00
2013-06-28 03:41:30 -04:00
When `require APP_PATH` is executed, `config/application.rb` is loaded (recall
that `APP_PATH` is defined in `bin/rails` ). This file exists in your application
and it's free for you to change based on your needs.
2012-06-10 21:26:54 -04:00
2012-09-01 21:37:59 -04:00
### `Rails::Server#start`
2010-12-14 23:08:08 -05:00
2013-11-12 08:44:10 -05:00
After `config/application` is loaded, `server.start` is called. This method is
defined like this:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rails
class Server < ::Rack::Server
def start(after_stop_callback = nil)
trap(:INT) { exit }
create_tmp_directories
setup_dev_caching
log_to_stdout if options[:log_stdout]
super()
2020-12-21 17:03:50 -05:00
# ...
2019-12-02 05:28:51 -05:00
end
2011-06-04 15:28:21 -04:00
2019-08-25 08:55:50 -04:00
private
def setup_dev_caching
if options[:environment] == "development"
Rails::DevCaching.enable_by_argument(options[:caching])
end
end
2013-11-12 08:44:10 -05:00
2019-08-25 08:55:50 -04:00
def create_tmp_directories
%w(cache pids sockets).each do |dir_to_make|
FileUtils.mkdir_p(File.join(Rails.root, "tmp", dir_to_make))
end
end
2017-08-19 20:41:37 -04:00
2019-08-25 08:55:50 -04:00
def log_to_stdout
wrapped_app # touch the app so the logger is set up
2017-08-19 20:41:37 -04:00
2019-08-25 08:55:50 -04:00
console = ActiveSupport::Logger.new(STDOUT)
console.formatter = Rails.logger.formatter
console.level = Rails.logger.level
unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
end
end
2012-05-23 11:45:48 -04:00
end
2019-08-25 08:55:50 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
This method creates a trap for `INT` signals, so if you `CTRL-C` the server, it will exit the process.
As we can see from the code here, it will create the `tmp/cache` ,
2016-12-20 14:13:22 -05:00
`tmp/pids` , and `tmp/sockets` directories. It then enables caching in development
2020-03-21 17:37:54 -04:00
if `bin/rails server` is called with `--dev-caching` . Finally, it calls `wrapped_app` which is
2015-01-03 13:20:54 -05:00
responsible for creating the Rack app, before creating and assigning an instance
of `ActiveSupport::Logger` .
2012-05-23 11:45:48 -04:00
2019-08-25 08:55:50 -04:00
The `super` method will call `Rack::Server.start` which begins its definition as follows:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
def start & blk
if options[:warn]
$-w = true
end
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
if includes = options[:include]
$LOAD_PATH.unshift(*includes)
end
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
if library = options[:require]
require library
end
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
if options[:debug]
$DEBUG = true
2020-03-29 19:30:52 -04:00
require "pp"
2019-08-25 08:55:50 -04:00
p options[:server]
pp wrapped_app
pp app
end
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
check_pid! if options[:pid]
2010-03-27 21:02:59 -04:00
2019-08-25 08:55:50 -04:00
# Touch the wrapped app, so that the config.ru is loaded before
# daemonization (i.e. before chdir, etc).
handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do
wrapped_app
end
daemonize_app if options[:daemonize]
2012-05-23 11:53:08 -04:00
2019-08-25 08:55:50 -04:00
write_pid if options[:pid]
2012-05-23 11:53:08 -04:00
2019-08-25 08:55:50 -04:00
trap(:INT) do
if server.respond_to?(:shutdown)
server.shutdown
else
exit
end
end
2012-05-23 11:53:08 -04:00
2019-08-25 08:55:50 -04:00
server.run wrapped_app, options, & blk
2012-05-23 11:53:08 -04:00
end
end
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2012-09-01 21:37:59 -04:00
The interesting part for a Rails app is the last line, `server.run` . Here we encounter the `wrapped_app` method again, which this time
2012-06-10 21:45:03 -04:00
we're going to explore more (even though it was executed before, and
2013-07-14 06:01:46 -04:00
thus memoized by now).
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
def wrapped_app
@wrapped_app ||= build_app app
end
end
end
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
The `app` method here is defined like so:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
def app
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
2010-03-27 21:02:59 -04:00
end
2020-12-21 17:03:50 -05:00
# ...
2011-06-04 15:28:21 -04:00
2019-08-25 08:55:50 -04:00
private
def build_app_and_options_from_config
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
@options .merge!(options) { |key, old, new| old }
app
end
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
end
2014-04-10 10:44:47 -04:00
end
2019-08-25 08:55:50 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
The `options[:config]` value defaults to `config.ru` which contains this:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
# This file is used by Rack-based servers to start the application.
2010-12-14 23:08:08 -05:00
2020-03-29 19:30:52 -04:00
require_relative "config/environment"
2019-08-25 08:55:50 -04:00
run Rails.application
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
The `Rack::Builder.parse_file` method here takes the content from this `config.ru` file and parses it using this code:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Builder
def self.load_file(path, opts = Server::Options.new)
2020-12-21 17:03:50 -05:00
# ...
2019-08-25 08:55:50 -04:00
app = new_from_string cfgfile, config
2020-12-21 17:03:50 -05:00
# ...
2019-08-25 08:55:50 -04:00
end
2014-04-10 10:44:47 -04:00
2020-12-21 17:03:50 -05:00
# ...
2014-04-10 10:44:47 -04:00
2019-08-25 08:55:50 -04:00
def self.new_from_string(builder_script, file="(rackup)")
eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
TOPLEVEL_BINDING, file, 0
end
end
2014-04-10 10:44:47 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2019-08-25 08:55:50 -04:00
The `initialize` method of `Rack::Builder` will take the block here and execute it within an instance of `Rack::Builder` .
This is where the majority of the initialization process of Rails happens.
The `require` line for `config/environment.rb` in `config.ru` is the first to run:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2020-03-29 19:30:52 -04:00
require_relative "config/environment"
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `config/environment.rb`
2010-12-14 23:08:08 -05:00
2020-03-21 17:37:54 -04:00
This file is the common file required by `config.ru` (`bin/rails server`) and Passenger. This is where these two ways to run the server meet; everything before this point has been Rack and Rails setup.
2010-03-27 21:02:59 -04:00
2014-04-10 10:44:47 -04:00
This file begins with requiring `config/application.rb` :
```ruby
2020-03-29 19:30:52 -04:00
require_relative "application"
2014-04-10 10:44:47 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `config/application.rb`
2010-12-14 23:08:08 -05:00
2014-04-10 10:44:47 -04:00
This file requires `config/boot.rb` :
```ruby
2020-03-29 19:30:52 -04:00
require_relative "boot"
2014-04-10 10:44:47 -04:00
```
2020-03-21 17:37:54 -04:00
But only if it hasn't been required before, which would be the case in `bin/rails server`
2014-04-10 10:44:47 -04:00
but **wouldn't** be the case with Passenger.
2010-12-14 23:08:08 -05:00
2011-04-13 20:49:14 -04:00
Then the fun begins!
2010-12-22 23:35:59 -05:00
2012-09-01 17:25:58 -04:00
Loading Rails
-------------
2010-12-22 23:35:59 -05:00
2012-09-01 21:37:59 -04:00
The next line in `config/application.rb` is:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2020-03-29 19:30:52 -04:00
require "rails/all"
2012-09-01 17:08:06 -04:00
```
2010-12-14 23:08:08 -05:00
2012-09-01 21:37:59 -04:00
### `railties/lib/rails/all.rb`
2010-12-14 23:08:08 -05:00
2012-06-17 14:30:20 -04:00
This file is responsible for requiring all the individual frameworks of Rails:
2010-12-14 23:08:08 -05:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
require "rails"
2010-12-14 23:08:08 -05:00
2011-06-04 15:28:21 -04:00
%w(
2015-12-30 16:30:29 -05:00
active_record/railtie
2018-02-27 03:10:25 -05:00
active_storage/engine
2015-12-30 16:30:29 -05:00
action_controller/railtie
action_view/railtie
action_mailer/railtie
active_job/railtie
action_cable/engine
2019-06-25 17:37:50 -04:00
action_mailbox/engine
action_text/engine
2015-12-30 16:30:29 -05:00
rails/test_unit/railtie
sprockets/railtie
).each do |railtie|
2011-06-04 15:28:21 -04:00
begin
2016-12-20 14:13:22 -05:00
require railtie
2011-06-04 15:28:21 -04:00
rescue LoadError
2010-03-27 21:02:59 -04:00
end
2011-06-04 15:28:21 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2012-06-10 21:45:03 -04:00
This is where all the Rails frameworks are loaded and thus made
2012-08-11 02:19:51 -04:00
available to the application. We won't go into detail of what happens
2012-06-10 21:45:03 -04:00
inside each of those frameworks, but you're encouraged to try and
explore them on your own.
2010-12-14 23:08:08 -05:00
2012-06-10 21:45:03 -04:00
For now, just keep in mind that common functionality like Rails engines,
2013-04-18 22:09:10 -04:00
I18n and Rails configuration are all being defined here.
2012-06-13 11:34:48 -04:00
2012-09-01 21:37:59 -04:00
### Back to `config/environment.rb`
2012-06-13 11:34:48 -04:00
2013-06-28 03:41:30 -04:00
The rest of `config/application.rb` defines the configuration for the
2014-02-10 09:32:01 -05:00
`Rails::Application` which will be used once the application is fully
2013-06-28 03:41:30 -04:00
initialized. When `config/application.rb` has finished loading Rails and defined
2015-05-27 15:15:13 -04:00
the application namespace, we go back to `config/environment.rb` . Here, the
application is initialized with `Rails.application.initialize!` , which is
2014-06-24 23:15:57 -04:00
defined in `rails/application.rb` .
2012-06-13 11:48:45 -04:00
2012-09-01 21:37:59 -04:00
### `railties/lib/rails/application.rb`
2012-06-13 11:48:45 -04:00
2012-09-01 21:37:59 -04:00
The `initialize!` method looks like this:
2012-06-13 11:48:45 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
def initialize!(group = :default) #:nodoc:
2012-06-13 11:48:45 -04:00
raise "Application has been already initialized." if @initialized
run_initializers(group, self)
@initialized = true
self
end
2012-09-01 17:08:06 -04:00
```
2012-06-13 11:48:45 -04:00
2020-12-18 16:36:26 -05:00
You can only initialize an app once. The Railtie [initializers ](configuring.html#initializers )
are run through the `run_initializers` method which is defined in
`railties/lib/rails/initializable.rb` :
2012-06-13 11:48:45 -04:00
2013-10-09 16:16:12 -04:00
```ruby
2019-08-25 08:55:50 -04:00
def run_initializers(group = :default, *args)
2013-10-09 16:16:12 -04:00
return if instance_variable_defined?(:@ran)
initializers.tsort_each do |initializer|
initializer.run(*args) if initializer.belongs_to?(group)
end
@ran = true
end
```
2012-06-13 11:48:45 -04:00
2014-04-19 06:19:53 -04:00
The `run_initializers` code itself is tricky. What Rails is doing here is
2013-10-09 16:16:12 -04:00
traversing all the class ancestors looking for those that respond to an
`initializers` method. It then sorts the ancestors by name, and runs them.
For example, the `Engine` class will make all the engines available by
providing an `initializers` method on them.
2012-06-13 11:48:45 -04:00
2013-06-28 03:41:30 -04:00
The `Rails::Application` class, as defined in `railties/lib/rails/application.rb`
defines `bootstrap` , `railtie` , and `finisher` initializers. The `bootstrap` initializers
prepare the application (like initializing the logger) while the `finisher`
initializers (like building the middleware stack) are run last. The `railtie`
initializers are the initializers which have been defined on the `Rails::Application`
itself and are run between the `bootstrap` and `finishers` .
2020-12-18 16:36:26 -05:00
*Note:* Do not confuse Railtie initializers overall with the [load_config_initializers ](configuring.html#using-initializer-files )
initializer instance or its associated config initializers in `config/initializers` .
2014-04-10 10:44:47 -04:00
After this is done we go back to `Rack::Server` .
2012-06-13 11:48:45 -04:00
2012-09-01 17:25:58 -04:00
### Rack: lib/rack/server.rb
2012-06-13 11:59:14 -04:00
2012-09-01 21:37:59 -04:00
Last time we left when the `app` method was being defined:
2012-06-13 11:59:14 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
def app
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
2012-06-13 11:59:14 -04:00
end
2020-12-21 17:03:50 -05:00
# ...
2012-06-13 11:59:14 -04:00
2019-08-25 08:55:50 -04:00
private
def build_app_and_options_from_config
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
@options .merge!(options) { |key, old, new| old }
app
end
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
end
2014-04-10 10:44:47 -04:00
end
2019-08-25 08:55:50 -04:00
end
2012-09-01 17:08:06 -04:00
```
2012-06-13 11:59:14 -04:00
2012-09-01 21:37:59 -04:00
At this point `app` is the Rails app itself (a middleware), and what
2012-06-13 11:59:14 -04:00
happens next is Rack will call all the provided middlewares:
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
class Server
private
def build_app(app)
middleware[options[:environment]].reverse_each do |middleware|
middleware = middleware.call(self) if middleware.respond_to?(:call)
next unless middleware
klass, *args = middleware
app = klass.new(app, *args)
end
app
end
2012-06-13 11:59:14 -04:00
end
end
2012-09-01 17:08:06 -04:00
```
2012-06-13 11:59:14 -04:00
2019-08-25 08:55:50 -04:00
Remember, `build_app` was called (by `wrapped_app` ) in the last line of `Rack::Server#start` .
2012-06-13 11:59:14 -04:00
Here's how it looked like when we left:
2012-09-01 17:08:06 -04:00
```ruby
2012-06-13 11:59:14 -04:00
server.run wrapped_app, options, & blk
2012-09-01 17:08:06 -04:00
```
2012-06-13 11:59:14 -04:00
2012-09-01 21:37:59 -04:00
At this point, the implementation of `server.run` will depend on the
2014-04-10 10:44:47 -04:00
server you're using. For example, if you were using Puma, here's what
2012-09-01 21:37:59 -04:00
the `run` method would look like:
2012-06-14 12:05:10 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2019-08-25 08:55:50 -04:00
module Rack
module Handler
module Puma
2020-12-21 17:03:50 -05:00
# ...
2019-08-25 08:55:50 -04:00
def self.run(app, options = {})
conf = self.config(app, options)
2014-04-10 10:44:47 -04:00
2019-08-25 08:55:50 -04:00
events = options.delete(:Silent) ? ::Puma::Events.strings : ::Puma::Events.stdio
2014-04-10 10:44:47 -04:00
2019-08-25 08:55:50 -04:00
launcher = ::Puma::Launcher.new(conf, :events => events)
2014-04-10 10:44:47 -04:00
2019-08-25 08:55:50 -04:00
yield launcher if block_given?
begin
launcher.run
rescue Interrupt
puts "* Gracefully stopping, waiting for requests to finish"
launcher.stop
puts "* Goodbye!"
end
end
2020-12-21 17:03:50 -05:00
# ...
2019-08-25 08:55:50 -04:00
end
2014-04-10 10:44:47 -04:00
end
2012-06-14 12:05:10 -04:00
end
2012-09-01 17:08:06 -04:00
```
2012-06-14 12:05:10 -04:00
2012-08-11 02:19:51 -04:00
We won't dig into the server configuration itself, but this is
2012-06-14 12:05:10 -04:00
the last piece of our journey in the Rails initialization process.
2012-08-11 02:19:51 -04:00
This high level overview will help you understand when your code is
2012-06-14 12:05:10 -04:00
executed and how, and overall become a better Rails developer. If you
still want to know more, the Rails source code itself is probably the
2014-06-29 14:14:40 -04:00
best place to go next.