mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
[ci skip] Update initialization guide samples.
Rewrite bits and pieces to mention the command infrastructure.
This commit is contained in:
parent
1bf6acb1ec
commit
e592ee20a9
1 changed files with 85 additions and 82 deletions
|
@ -74,7 +74,7 @@ This file is as follows:
|
|||
|
||||
```ruby
|
||||
#!/usr/bin/env ruby
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
APP_PATH = File.expand_path('../config/application', __dir__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
```
|
||||
|
@ -86,7 +86,7 @@ The `APP_PATH` constant will be used later in `rails/commands`. The `config/boot
|
|||
`config/boot.rb` contains:
|
||||
|
||||
```ruby
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||
|
||||
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||
```
|
||||
|
@ -131,7 +131,7 @@ Once `config/boot.rb` has finished, the next file that is required is
|
|||
`ARGV` array simply contains `server` which will be passed over:
|
||||
|
||||
```ruby
|
||||
ARGV << '--help' if ARGV.empty?
|
||||
require "rails/command"
|
||||
|
||||
aliases = {
|
||||
"g" => "generate",
|
||||
|
@ -146,33 +146,37 @@ aliases = {
|
|||
command = ARGV.shift
|
||||
command = aliases[command] || command
|
||||
|
||||
require 'rails/commands/commands_tasks'
|
||||
|
||||
Rails::CommandsTasks.new(ARGV).run_command!(command)
|
||||
Rails::Command.invoke command, ARGV
|
||||
```
|
||||
|
||||
TIP: As you can see, an empty ARGV list will make Rails show the help
|
||||
snippet.
|
||||
|
||||
If we had used `s` rather than `server`, Rails would have used the `aliases`
|
||||
defined here to find the matching command.
|
||||
|
||||
### `rails/commands/commands_tasks.rb`
|
||||
### `rails/command.rb`
|
||||
|
||||
When one types a valid Rails command, `run_command!` a method of the same name
|
||||
is called. If Rails doesn't recognize the command, it tries to run a Rake task
|
||||
of the same name.
|
||||
When one types a Rails command, `invoke` tries to lookup a command for the given
|
||||
namespace and executing the command if found.
|
||||
|
||||
If Rails doesn't recognize the command, it hands the reins over to Rake
|
||||
to run a task of the same name.
|
||||
|
||||
As shown, `Rails::Command` displays the help output automatically if the `args`
|
||||
are empty.
|
||||
|
||||
```ruby
|
||||
COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole application runner new version help)
|
||||
module Rails::Command
|
||||
class << self
|
||||
def invoke(namespace, args = [], **config)
|
||||
namespace = namespace.to_s
|
||||
namespace = "help" if namespace.blank? || Thor::HELP_MAPPINGS.include?(namespace)
|
||||
namespace = "version" if %w( -v --version ).include? namespace
|
||||
|
||||
def run_command!(command)
|
||||
command = parse_command(command)
|
||||
|
||||
if COMMAND_WHITELIST.include?(command)
|
||||
send(command)
|
||||
if command = find_by_namespace(namespace)
|
||||
command.perform(namespace, args, config)
|
||||
else
|
||||
run_rake_task(command)
|
||||
find_by_namespace("rake").perform(namespace, args, config)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
@ -180,53 +184,39 @@ end
|
|||
With the `server` command, Rails will further run the following code:
|
||||
|
||||
```ruby
|
||||
def set_application_directory!
|
||||
Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
|
||||
end
|
||||
|
||||
def server
|
||||
module Rails
|
||||
module Command
|
||||
class ServerCommand < Base # :nodoc:
|
||||
def perform
|
||||
set_application_directory!
|
||||
require_command!("server")
|
||||
|
||||
Rails::Server.new.tap do |server|
|
||||
# We need to require application after the server sets environment,
|
||||
# otherwise the --environment option given to the server won't propagate.
|
||||
# Require application after server sets environment to propagate
|
||||
# the --environment option.
|
||||
require APP_PATH
|
||||
Dir.chdir(Rails.application.root)
|
||||
server.start
|
||||
end
|
||||
end
|
||||
|
||||
def require_command!(command)
|
||||
require "rails/commands/#{command}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
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 requires `rails/commands/server` which
|
||||
sets up the `Rails::Server` class.
|
||||
|
||||
```ruby
|
||||
require 'fileutils'
|
||||
require 'optparse'
|
||||
require 'action_dispatch'
|
||||
require 'rails'
|
||||
|
||||
module Rails
|
||||
class Server < ::Rack::Server
|
||||
```
|
||||
|
||||
`fileutils` and `optparse` are standard Ruby libraries which provide helper functions for working with files and parsing options.
|
||||
`config.ru` file isn't found. This then starts up the `Rails::Server` class.
|
||||
|
||||
### `actionpack/lib/action_dispatch.rb`
|
||||
|
||||
Action Dispatch is the routing component of the Rails framework.
|
||||
It adds functionality like routing, session, and common middlewares.
|
||||
|
||||
### `rails/commands/server.rb`
|
||||
### `rails/commands/server/server_command.rb`
|
||||
|
||||
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.rb`:
|
||||
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`:
|
||||
|
||||
```ruby
|
||||
def initialize(*)
|
||||
|
@ -252,7 +242,10 @@ end
|
|||
|
||||
In this case, `options` will be `nil` so nothing happens in this method.
|
||||
|
||||
After `super` has finished in `Rack::Server`, we jump back to `rails/commands/server.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:
|
||||
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:
|
||||
|
||||
```ruby
|
||||
def set_environment
|
||||
|
@ -289,17 +282,15 @@ With the `default_options` set to this:
|
|||
|
||||
```ruby
|
||||
def default_options
|
||||
environment = ENV['RACK_ENV'] || 'development'
|
||||
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
||||
|
||||
{
|
||||
:environment => environment,
|
||||
:pid => nil,
|
||||
:Port => 9292,
|
||||
:Host => default_host,
|
||||
:AccessLog => [],
|
||||
:config => "config.ru"
|
||||
}
|
||||
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)
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -311,22 +302,25 @@ def opt_parser
|
|||
end
|
||||
```
|
||||
|
||||
The class **is** defined in `Rack::Server`, but is overwritten in `Rails::Server` to take different arguments. Its `parse!` method begins like this:
|
||||
The class **is** defined in `Rack::Server`, but is overwritten in
|
||||
`Rails::Server` to take different arguments. Its `parse!` method looks
|
||||
like this:
|
||||
|
||||
```ruby
|
||||
def parse!(args)
|
||||
args, options = args.dup, {}
|
||||
|
||||
opt_parser = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: rails server [puma, thin, etc] [options]"
|
||||
opts.on("-p", "--port=port", Integer,
|
||||
"Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
|
||||
...
|
||||
option_parser(options).parse! args
|
||||
|
||||
options[:log_stdout] = options[:daemonize].blank? && (options[:environment] || Rails.env) == "development"
|
||||
options[:server] = args.shift
|
||||
options
|
||||
end
|
||||
```
|
||||
|
||||
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 `rails/server` where `APP_PATH` (which was
|
||||
has finished, we jump back into the server command where `APP_PATH` (which was
|
||||
set earlier) is required.
|
||||
|
||||
### `config/application`
|
||||
|
@ -345,6 +339,7 @@ def start
|
|||
print_boot_information
|
||||
trap(:INT) { exit }
|
||||
create_tmp_directories
|
||||
setup_dev_caching
|
||||
log_to_stdout if options[:log_stdout]
|
||||
|
||||
super
|
||||
|
@ -352,7 +347,6 @@ def start
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
def print_boot_information
|
||||
...
|
||||
puts "=> Run `rails server -h` for more startup options"
|
||||
|
@ -364,21 +358,30 @@ private
|
|||
end
|
||||
end
|
||||
|
||||
def setup_dev_caching
|
||||
if options[:environment] == "development"
|
||||
Rails::DevCaching.enable_by_argument(options[:caching])
|
||||
end
|
||||
end
|
||||
|
||||
def log_to_stdout
|
||||
wrapped_app # touch the app so the logger is set up
|
||||
|
||||
console = ActiveSupport::Logger.new($stdout)
|
||||
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
|
||||
```
|
||||
|
||||
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 calls `wrapped_app` which is
|
||||
`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`.
|
||||
|
||||
|
@ -538,7 +541,7 @@ require "rails"
|
|||
sprockets/railtie
|
||||
).each do |railtie|
|
||||
begin
|
||||
require "#{railtie}"
|
||||
require railtie
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue