This guide goes through every method call that is
required to boot up the Ruby on Rails stack for a default Rails
application, explaining each part in detail along the way. For this
guide, we will be focusing on what happens when you execute rails server
to boot your app.

Paths in this guide are relative to Rails or a Rails application unless otherwise specified.

If you want to follow along while browsing the Rails source
code, we recommend that you use the t
key binding to open the file finder inside GitHub and find files
quickly.

The primary goal of the function exec_app is to execute your app's
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.

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.

In a standard Rails application, there's a Gemfile which declares all
dependencies of the application. config/boot.rb sets
ENV['BUNDLE_GEMFILE'] to the location of this file. If the Gemfile
exists, then bundler/setup is required. The require is used by Bundler to
configure the load path for your Gemfile's dependencies.

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
ARGV array simply contains server which will be passed over:

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
config.ru file isn't found. This then starts up the Rails::Server class.

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:

def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end

In fact, the options method here does quite a lot. This method is defined in Rack::Server like this:

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
has finished, we jump back into the server command where APP_PATH (which was
set earlier) is required.

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.

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,
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
responsible for creating the Rack app, before creating and assigning an instance
of ActiveSupport::Logger.

The super method will call Rack::Server.start which begins its definition like this:

def start &blk
if options[:warn]
$-w = true
end
if includes = options[:include]
$LOAD_PATH.unshift(*includes)
end
if library = options[:require]
require library
end
if options[:debug]
$DEBUG = true
require 'pp'
p options[:server]
pp wrapped_app
pp app
end
check_pid! if options[:pid]
# 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

The interesting part for a Rails app is the last line, server.run. Here we encounter the wrapped_app method again, which this time
we're going to explore more (even though it was executed before, and
thus memoized by now).

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:

This is where all the Rails frameworks are loaded and thus made
available to the application. We won't go into detail of what happens
inside each of those frameworks, but you're encouraged to try and
explore them on your own.

For now, just keep in mind that common functionality like Rails engines,
I18n and Rails configuration are all being defined here.

The rest of config/application.rb defines the configuration for the
Rails::Application which will be used once the application is fully
initialized. When config/application.rb has finished loading Rails and defined
the application namespace, we go back to config/environment.rb. Here, the
application is initialized with Rails.application.initialize!, which is
defined in rails/application.rb.

The run_initializers code itself is tricky. What Rails is doing here is
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.

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.

We won't dig into the server configuration itself, but this is
the last piece of our journey in the Rails initialization process.

This high level overview will help you understand when your code is
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
best place to go next.

Feedback

You may also find incomplete content or stuff that is not up to date.
Please do add any missing documentation for master. Make sure to check
Edge Guides first to verify
if the issues are already fixed or not on the master branch.
Check the Ruby on Rails Guides Guidelines
for style and conventions.

If for whatever reason you spot something to fix but cannot patch it yourself, please
open an issue.