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:
2012-12-07 12:50:09 -05:00
* How to use `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
2013-06-28 03:41:30 -04:00
guide, we will be focusing on what happens when you execute `rails server`
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
started by running `rails console` or `rails server` .
2015-04-11 12:44:27 -04:00
### `railties/exe/rails`
2013-11-06 07:54:22 -05:00
The `rails` in the command `rails server` is a ruby executable in your load
path. This executable contains the following lines:
```ruby
version = ">= 0"
load Gem.bin_path('railties', 'rails', version)
```
If you try out this command in a Rails console, you would see that this loads
2018-07-02 03:03:23 -04:00
`railties/exe/rails` . A part of the file `railties/exe/rails` has the
2013-11-06 07:54:22 -05:00
following code:
```ruby
require "rails/cli"
```
The file `railties/lib/rails/cli` in turn calls
2015-04-22 23:05:30 -04:00
`Rails::AppLoader.exec_app` .
2013-11-06 07:54:22 -05:00
2015-04-22 23:05:30 -04:00
### `railties/lib/rails/app_loader.rb`
2013-11-06 07:54:22 -05:00
2015-04-22 23:05:30 -04:00
The primary goal of the function `exec_app` is to execute your app's
2013-11-06 07:54:22 -05:00
`bin/rails` . If the current directory does not have a `bin/rails` , it will
navigate upwards until it finds a `bin/rails` executable. Thus one can invoke a
`rails` command from anywhere inside a rails application.
For `rails server` the equivalent of the following command is executed:
```bash
$ exec ruby 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__ )
2013-08-12 04:15:20 -04:00
require_relative '../config/boot'
2011-06-04 15:28:21 -04:00
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
2015-10-26 15:19:07 -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
* 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
2017-08-19 20:41:37 -04:00
require_relative "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
2016-12-20 14:13:22 -05:00
As shown, `Rails::Command` displays the help output automatically if the `args`
are empty.
2015-11-13 19:58:51 -05:00
2016-12-20 14:13:22 -05:00
```ruby
module Rails::Command
class < < self
def invoke(namespace, args = [], **config)
namespace = namespace.to_s
2017-01-17 00:09:00 -05:00
namespace = "help" if namespace.blank? || HELP_MAPPINGS.include?(namespace)
2016-12-20 14:13:22 -05:00
namespace = "version" if %w( -v --version ).include? namespace
2017-08-19 20:41:37 -04:00
2016-12-20 14:13:22 -05:00
if command = find_by_namespace(namespace)
command.perform(namespace, args, config)
else
find_by_namespace("rake").perform(namespace, args, config)
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
set_application_directory!
2017-08-19 20:41:37 -04:00
2016-12-20 14:13:22 -05:00
Rails::Server.new.tap do |server|
# Require application after server sets environment to propagate
# the --environment option.
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
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
2011-06-04 15:28:21 -04:00
def initialize(*)
super
set_environment
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
2012-09-01 21:37:59 -04:00
The `initialize` method in `Rack::Server` simply sets a couple of variables:
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
def initialize(options = nil)
@options = options
@app = options[:app] if options && options[:app]
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
In this case, `options` will be `nil` so nothing happens in this method.
2010-03-27 21:02:59 -04:00
2016-12-20 14:13:22 -05: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 and this method
doesn't appear to do much at first glance:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end
2012-09-01 17:08:06 -04:00
```
2010-03-31 05:50:13 -04:00
2012-09-01 21:37:59 -04:00
In fact, the `options` method here does quite a lot. This method is defined in `Rack::Server` like this:
2010-03-31 05:50:13 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def options
@options ||= parse_options(ARGV)
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
Then `parse_options` is defined like this:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def parse_options(args)
options = default_options
2010-03-31 05:50:13 -04:00
2011-06-04 15:28:21 -04:00
# Don't evaluate CGI ISINDEX parameters.
2014-02-10 09:32:01 -05:00
# http://www.meb.uni-bonn.de/docs/cgi/cl.html
2011-06-04 15:28:21 -04:00
args.clear if ENV.include?("REQUEST_METHOD")
2010-03-27 21:02:59 -04:00
2014-04-10 10:44:47 -04:00
options.merge! opt_parser.parse!(args)
2011-06-04 15:28:21 -04:00
options[:config] = ::File.expand_path(options[:config])
2015-03-20 11:14:11 -04:00
ENV["RACK_ENV"] = options[:environment]
2011-06-04 15:28:21 -04:00
options
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
With the `default_options` set to this:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def default_options
2016-12-20 14:13:22 -05:00
super.merge(
Port: ENV.fetch("PORT", 3000).to_i,
Host: ENV.fetch("HOST", "localhost").dup,
DoNotReverseLookup: true,
environment: (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup,
daemonize: false,
caching: nil,
pid: Options::DEFAULT_PID_PATH,
restart_cmd: restart_command)
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
2014-06-24 23:15:57 -04:00
There is no `REQUEST_METHOD` key in `ENV` so we can skip over that line. The next line merges in the options from `opt_parser` which is defined plainly in `Rack::Server` :
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def opt_parser
Options.new
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2016-12-20 14:13:22 -05:00
The class **is** defined in `Rack::Server` , but is overwritten in
`Rails::Server` to take different arguments. Its `parse!` method looks
like this:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2011-06-04 15:28:21 -04:00
def parse!(args)
args, options = args.dup, {}
2010-12-14 23:08:08 -05:00
2016-12-20 14:13:22 -05:00
option_parser(options).parse! args
2017-08-19 20:41:37 -04:00
2016-12-20 14:13:22 -05:00
options[:log_stdout] = options[:daemonize].blank? & & (options[:environment] || Rails.env) == "development"
options[:server] = args.shift
options
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
This method will set up keys for the `options` which Rails will then be
able to use to determine how its server should run. After `initialize`
2016-12-20 14:13:22 -05:00
has finished, we jump back into the server command where `APP_PATH` (which was
2012-06-10 21:20:40 -04:00
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
2011-06-04 15:28:21 -04:00
def start
2013-11-12 08:44:10 -05:00
print_boot_information
2011-06-04 15:28:21 -04:00
trap(:INT) { exit }
2013-11-12 08:44:10 -05:00
create_tmp_directories
2016-12-20 14:13:22 -05:00
setup_dev_caching
2013-11-12 08:44:10 -05:00
log_to_stdout if options[:log_stdout]
2011-06-04 15:28:21 -04:00
2013-11-12 08:44:10 -05:00
super
...
end
private
def print_boot_information
...
puts "=> Run `rails server -h` for more startup options"
2010-03-31 05:50:13 -04:00
end
2011-06-04 15:28:21 -04:00
2013-11-12 08:44:10 -05:00
def create_tmp_directories
2015-01-03 13:20:54 -05:00
%w(cache pids sockets).each do |dir_to_make|
2013-11-12 08:44:10 -05:00
FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make))
end
end
2016-12-20 14:13:22 -05:00
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
def log_to_stdout
2012-05-23 11:45:48 -04:00
wrapped_app # touch the app so the logger is set up
2017-08-19 20:41:37 -04:00
2016-12-20 14:13:22 -05:00
console = ActiveSupport::Logger.new(STDOUT)
2012-05-23 11:45:48 -04:00
console.formatter = Rails.logger.formatter
2013-11-12 08:44:10 -05:00
console.level = Rails.logger.level
2017-08-19 20:41:37 -04:00
2016-12-20 14:13:22 -05:00
unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
end
2012-05-23 11:45:48 -04:00
end
2012-09-01 17:08:06 -04:00
```
2010-03-27 21:02:59 -04:00
2015-01-03 13:20:54 -05:00
This is where the first output of the Rails initialization happens. 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
if `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
2012-09-01 21:37:59 -04:00
The `super` method will call `Rack::Server.start` which begins its definition like this:
2010-03-27 21:02:59 -04:00
2012-09-01 17:08:06 -04:00
```ruby
2012-05-23 11:53:08 -04:00
def start & blk
2011-06-04 15:28:21 -04:00
if options[:warn]
$-w = true
end
2010-12-14 23:08:08 -05:00
2011-06-04 15:28:21 -04:00
if includes = options[:include]
$LOAD_PATH.unshift(*includes)
end
2010-12-14 23:08:08 -05:00
2011-06-04 15:28:21 -04:00
if library = options[:require]
require library
end
2010-12-14 23:08:08 -05:00
2011-06-04 15:28:21 -04:00
if options[:debug]
$DEBUG = true
require 'pp'
p options[:server]
pp wrapped_app
pp app
end
2010-03-27 21:02:59 -04:00
2012-05-23 11:53:08 -04:00
check_pid! if options[:pid]
2010-03-27 21:02:59 -04:00
2012-05-23 11:53:08 -04:00
# Touch the wrapped app, so that the config.ru is loaded before
# daemonization (i.e. before chdir, etc).
wrapped_app
daemonize_app if options[:daemonize]
write_pid if options[:pid]
trap(:INT) do
if server.respond_to?(:shutdown)
server.shutdown
else
exit
end
end
server.run wrapped_app, options, & blk
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
2011-06-04 15:28:21 -04:00
@wrapped_app ||= build_app app
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
2011-06-04 15:28:21 -04:00
def app
2014-04-10 10:44:47 -04:00
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
end
...
private
def build_app_and_options_from_config
2011-06-04 15:28:21 -04:00
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
2010-03-27 21:02:59 -04:00
end
2011-06-04 15:28:21 -04:00
app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
self.options.merge! options
app
2010-12-14 23:08:08 -05:00
end
2014-04-10 10:44:47 -04:00
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
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
2016-07-06 16:24:57 -04:00
require_relative 'config/environment'
2012-05-23 12:01:21 -04:00
run < %= app_const %>
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
2014-04-10 10:44:47 -04:00
app = new_from_string cfgfile, config
...
def self.new_from_string(builder_script, file="(rackup)")
eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
TOPLEVEL_BINDING, file, 0
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 `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
2016-07-06 16:24:57 -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
2012-09-01 21:37:59 -04:00
This file is the common file required by `config.ru` (`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
2016-07-06 16:24:57 -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
2016-07-06 16:24:57 -04:00
require_relative 'boot'
2014-04-10 10:44:47 -04:00
```
But only if it hasn't been required before, which would be the case in `rails server`
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
2011-06-04 15:28:21 -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
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
2012-06-13 11:48:45 -04:00
def initialize!(group=:default) #:nodoc:
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
2013-10-09 16:16:12 -04:00
As you can see, you can only initialize an app once. The initializers are run through
2014-06-24 23:15:57 -04:00
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
def run_initializers(group=:default, *args)
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` .
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
2012-06-13 11:59:14 -04:00
def app
2014-04-10 10:44:47 -04:00
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
end
...
private
def build_app_and_options_from_config
2012-06-13 11:59:14 -04:00
if !::File.exist? options[:config]
abort "configuration #{options[:config]} not found"
end
app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
self.options.merge! options
app
end
2014-04-10 10:44:47 -04:00
def build_app_from_string
Rack::Builder.new_from_string(self.options[:builder])
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
2012-06-13 11:59:14 -04:00
def build_app(app)
middleware[options[:environment]].reverse_each do |middleware|
middleware = middleware.call(self) if middleware.respond_to?(:call)
next unless middleware
klass = middleware.shift
app = klass.new(app, *middleware)
end
app
end
2012-09-01 17:08:06 -04:00
```
2012-06-13 11:59:14 -04:00
2014-04-19 06:19:53 -04:00
Remember, `build_app` was called (by `wrapped_app` ) in the last line of `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
2014-04-10 10:44:47 -04:00
...
DEFAULT_OPTIONS = {
:Host => '0.0.0.0',
:Port => 8080,
:Threads => '0:16',
:Verbose => false
}
def self.run(app, options = {})
2016-09-05 08:14:47 -04:00
options = DEFAULT_OPTIONS.merge(options)
2014-04-10 10:44:47 -04:00
if options[:Verbose]
app = Rack::CommonLogger.new(app, STDOUT)
2012-06-14 12:05:10 -04:00
end
2014-04-10 10:44:47 -04:00
if options[:environment]
2015-03-20 11:14:11 -04:00
ENV['RACK_ENV'] = options[:environment].to_s
2014-04-10 10:44:47 -04:00
end
server = ::Puma::Server.new(app)
min, max = options[:Threads].split(':', 2)
puts "Puma #{::Puma::Const::PUMA_VERSION} starting..."
puts "* Min threads: #{min}, max threads: #{max}"
2015-03-20 11:14:11 -04:00
puts "* Environment: #{ENV['RACK_ENV']}"
2014-04-10 10:44:47 -04:00
puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
server.add_tcp_listener options[:Host], options[:Port]
server.min_threads = min
server.max_threads = max
2013-05-28 08:36:18 -04:00
yield server if block_given?
2014-04-10 10:44:47 -04:00
begin
server.run.join
rescue Interrupt
puts "* Gracefully stopping, waiting for requests to finish"
server.stop(true)
puts "* Goodbye!"
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.