mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
correct code indendation in the initialization guide
This commit is contained in:
parent
087f8e16a6
commit
9f19322b1f
1 changed files with 305 additions and 304 deletions
|
@ -20,15 +20,15 @@ h4. +bin/rails+
|
|||
The actual +rails+ command is kept in _bin/rails_ at the and goes like this:
|
||||
|
||||
<ruby>
|
||||
#!/usr/bin/env ruby
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
begin
|
||||
require "rails/cli"
|
||||
rescue LoadError
|
||||
railties_path = File.expand_path('../../railties/lib', __FILE__)
|
||||
$:.unshift(railties_path)
|
||||
require "rails/cli"
|
||||
end
|
||||
begin
|
||||
require "rails/cli"
|
||||
rescue LoadError
|
||||
railties_path = File.expand_path('../../railties/lib', __FILE__)
|
||||
$:.unshift(railties_path)
|
||||
require "rails/cli"
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This file will attempt to load +rails/cli+ and if it cannot find it then add the +railties/lib+ path to the load path (+$:+) and will then try to require it again.
|
||||
|
@ -38,22 +38,22 @@ h4. +railites/lib/rails/cli.rb+
|
|||
This file looks like this:
|
||||
|
||||
<ruby>
|
||||
require 'rbconfig'
|
||||
require 'rails/script_rails_loader'
|
||||
require 'rbconfig'
|
||||
require 'rails/script_rails_loader'
|
||||
|
||||
# If we are inside a Rails application this method performs an exec and thus
|
||||
# the rest of this script is not run.
|
||||
Rails::ScriptRailsLoader.exec_script_rails!
|
||||
# If we are inside a Rails application this method performs an exec and thus
|
||||
# the rest of this script is not run.
|
||||
Rails::ScriptRailsLoader.exec_script_rails!
|
||||
|
||||
require 'rails/ruby_version_check'
|
||||
Signal.trap("INT") { puts; exit }
|
||||
require 'rails/ruby_version_check'
|
||||
Signal.trap("INT") { puts; exit }
|
||||
|
||||
if ARGV.first == 'plugin'
|
||||
ARGV.shift
|
||||
require 'rails/commands/plugin_new'
|
||||
else
|
||||
require 'rails/commands/application'
|
||||
end
|
||||
if ARGV.first == 'plugin'
|
||||
ARGV.shift
|
||||
require 'rails/commands/plugin_new'
|
||||
else
|
||||
require 'rails/commands/application'
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +rbconfig+ file here is out of Ruby's standard library and provides us with the +RbConfig+ class which contains useful information dependent on how Ruby was compiled. We'll see this in use in +railties/lib/rails/script_rails_loader+.
|
||||
|
@ -76,46 +76,46 @@ The +rails/script_rails_loader+ file uses +RbConfig::Config+ to gather up the +b
|
|||
Back in +rails/cli+, the next line is this:
|
||||
|
||||
<ruby>
|
||||
Rails::ScriptRailsLoader.exec_script_rails!
|
||||
Rails::ScriptRailsLoader.exec_script_rails!
|
||||
</ruby>
|
||||
|
||||
This method is defined in +rails/script_rails_loader+ like this:
|
||||
|
||||
<ruby>
|
||||
def self.exec_script_rails!
|
||||
cwd = Dir.pwd
|
||||
return unless in_rails_application? || in_rails_application_subdirectory?
|
||||
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
|
||||
Dir.chdir("..") do
|
||||
# Recurse in a chdir block: if the search fails we want to be sure
|
||||
# the application is generated in the original working directory.
|
||||
exec_script_rails! unless cwd == Dir.pwd
|
||||
end
|
||||
rescue SystemCallError
|
||||
# could not chdir, no problem just return
|
||||
def self.exec_script_rails!
|
||||
cwd = Dir.pwd
|
||||
return unless in_rails_application? || in_rails_application_subdirectory?
|
||||
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
|
||||
Dir.chdir("..") do
|
||||
# Recurse in a chdir block: if the search fails we want to be sure
|
||||
# the application is generated in the original working directory.
|
||||
exec_script_rails! unless cwd == Dir.pwd
|
||||
end
|
||||
rescue SystemCallError
|
||||
# could not chdir, no problem just return
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This method will first check if the current working directory (+cwd+) is a Rails application or is a subdirectory of one. The way to determine this is defined in the +in_rails_application?+ method like this:
|
||||
|
||||
<ruby>
|
||||
def self.in_rails_application?
|
||||
File.exists?(SCRIPT_RAILS)
|
||||
end
|
||||
def self.in_rails_application?
|
||||
File.exists?(SCRIPT_RAILS)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+, then +in_rails_application_subdirectory?+ will be used:
|
||||
|
||||
<ruby>
|
||||
def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
|
||||
File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
|
||||
end
|
||||
def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
|
||||
File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory is reached which contains this file then this line will run:
|
||||
|
||||
<ruby>
|
||||
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
|
||||
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
|
||||
</ruby>
|
||||
|
||||
This is effectively the same as doing +ruby script/rails [arguments]+. Where +[arguments]+ at this point in time is simply "server".
|
||||
|
@ -125,9 +125,9 @@ h4. +script/rails+
|
|||
This file looks like this:
|
||||
|
||||
<ruby>
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require File.expand_path('../../config/boot', __FILE__)
|
||||
require 'rails/commands'
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require File.expand_path('../../config/boot', __FILE__)
|
||||
require 'rails/commands'
|
||||
</ruby>
|
||||
|
||||
The +APP_PATH+ constant here will be used later in +rails/commands+. The +config/boot+ file that +script/rails+ references is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
|
||||
|
@ -137,19 +137,19 @@ h4. +config/boot.rb+
|
|||
+config/boot.rb+ contains this:
|
||||
|
||||
<ruby>
|
||||
require 'rubygems'
|
||||
require 'rubygems'
|
||||
|
||||
# Set up gems listed in the Gemfile.
|
||||
gemfile = File.expand_path('../../Gemfile', __FILE__)
|
||||
begin
|
||||
ENV['BUNDLE_GEMFILE'] = gemfile
|
||||
require 'bundler'
|
||||
Bundler.setup
|
||||
rescue Bundler::GemNotFound => e
|
||||
STDERR.puts e.message
|
||||
STDERR.puts "Try running `bundle install`."
|
||||
exit!
|
||||
end if File.exist?(gemfile)
|
||||
# Set up gems listed in the Gemfile.
|
||||
gemfile = File.expand_path('../../Gemfile', __FILE__)
|
||||
begin
|
||||
ENV['BUNDLE_GEMFILE'] = gemfile
|
||||
require 'bundler'
|
||||
Bundler.setup
|
||||
rescue Bundler::GemNotFound => e
|
||||
STDERR.puts e.message
|
||||
STDERR.puts "Try running `bundle install`."
|
||||
exit!
|
||||
end if File.exist?(gemfile)
|
||||
</ruby>
|
||||
|
||||
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, then requires Bundler and calls +Bundler.setup+ which adds the dependencies of the application (including all the Rails parts) to the load path, making them available for the application to load. The gems that a Rails 3.1 application depends on are as follows:
|
||||
|
@ -186,34 +186,34 @@ h4. +rails/commands.rb+
|
|||
Once +config/boot.rb+ has finished, the next file that is required is +rails/commands+ which will execute a command based on the arguments passed in. In this case, the +ARGV+ array simply contains +server+ which is extracted into the +command+ variable using these lines:
|
||||
|
||||
<ruby>
|
||||
aliases = {
|
||||
"g" => "generate",
|
||||
"c" => "console",
|
||||
"s" => "server",
|
||||
"db" => "dbconsole"
|
||||
}
|
||||
aliases = {
|
||||
"g" => "generate",
|
||||
"c" => "console",
|
||||
"s" => "server",
|
||||
"db" => "dbconsole"
|
||||
}
|
||||
|
||||
command = ARGV.shift
|
||||
command = aliases[command] || command
|
||||
command = ARGV.shift
|
||||
command = aliases[command] || command
|
||||
</ruby>
|
||||
|
||||
If we used <tt>s</tt> rather than +server+, Rails will use the +aliases+ defined in the file and match them to their respective commands. With the +server+ command, Rails will run this code:
|
||||
|
||||
<ruby>
|
||||
when 'server'
|
||||
# Change to the application's path if there is no config.ru file in current dir.
|
||||
# This allows us to run script/rails server from other directories, but still get
|
||||
# the main config.ru and properly set the tmp directory.
|
||||
Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
|
||||
when 'server'
|
||||
# Change to the application's path if there is no config.ru file in current dir.
|
||||
# This allows us to run script/rails server from other directories, but still get
|
||||
# the main config.ru and properly set the tmp directory.
|
||||
Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
|
||||
|
||||
require 'rails/commands/server'
|
||||
Rails::Server.new.tap { |server|
|
||||
# We need to require application after the server sets environment,
|
||||
# otherwise the --environment option given to the server won't propagate.
|
||||
require APP_PATH
|
||||
Dir.chdir(Rails.application.root)
|
||||
server.start
|
||||
}
|
||||
require 'rails/commands/server'
|
||||
Rails::Server.new.tap { |server|
|
||||
# We need to require application after the server sets environment,
|
||||
# otherwise the --environment option given to the server won't propagate.
|
||||
require APP_PATH
|
||||
Dir.chdir(Rails.application.root)
|
||||
server.start
|
||||
}
|
||||
</ruby>
|
||||
|
||||
This file will change into the root of the directory (a path two directories back 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 requires +action_dispatch+ and sets up the +Rails::Server+ class.
|
||||
|
@ -239,7 +239,7 @@ The +methods.rb+ file is responsible for defining methods such as +camelize+, +u
|
|||
In this file there are a lot of lines such as this inside the +ActiveSupport+ module:
|
||||
|
||||
<ruby>
|
||||
autoload :Inflector
|
||||
autoload :Inflector
|
||||
</ruby>
|
||||
|
||||
Due to the overriding of the +autoload+ method, Ruby will know to look for this file at +activesupport/lib/active_support/inflector.rb+ when the +Inflector+ class is first referenced.
|
||||
|
@ -263,10 +263,10 @@ h4. +rails/commands/server.rb+
|
|||
The +Rails::Server+ class is defined in this file as inheriting from +Rack::Server+. When +Rails::Server.new+ is called, this calls the +initialize+ method in +rails/commands/server.rb+:
|
||||
|
||||
<ruby>
|
||||
def initialize(*)
|
||||
super
|
||||
set_environment
|
||||
end
|
||||
def initialize(*)
|
||||
super
|
||||
set_environment
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Firstly, +super+ is called which calls the +initialize+ method on +Rack::Server+.
|
||||
|
@ -278,10 +278,10 @@ h4. Rack: +lib/rack/server.rb+
|
|||
The +initialize+ method in +Rack::Server+ simply sets a couple of variables:
|
||||
|
||||
<ruby>
|
||||
def initialize(options = nil)
|
||||
@options = options
|
||||
@app = options[:app] if options && options[:app]
|
||||
end
|
||||
def initialize(options = nil)
|
||||
@options = options
|
||||
@app = options[:app] if options && options[:app]
|
||||
end
|
||||
</ruby>
|
||||
|
||||
In this case, +options+ will be +nil+ so nothing happens in this method.
|
||||
|
@ -289,64 +289,64 @@ 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:
|
||||
|
||||
<ruby>
|
||||
def set_environment
|
||||
ENV["RAILS_ENV"] ||= options[:environment]
|
||||
end
|
||||
def set_environment
|
||||
ENV["RAILS_ENV"] ||= options[:environment]
|
||||
end
|
||||
</ruby>
|
||||
|
||||
In fact, the +options+ method here does quite a lot. This method is defined in +Rack::Server+ like this:
|
||||
|
||||
<ruby>
|
||||
def options
|
||||
@options ||= parse_options(ARGV)
|
||||
end
|
||||
def options
|
||||
@options ||= parse_options(ARGV)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Then +parse_options+ is defined like this:
|
||||
|
||||
<ruby>
|
||||
def parse_options(args)
|
||||
options = default_options
|
||||
def parse_options(args)
|
||||
options = default_options
|
||||
|
||||
# Don't evaluate CGI ISINDEX parameters.
|
||||
# http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
|
||||
args.clear if ENV.include?("REQUEST_METHOD")
|
||||
# Don't evaluate CGI ISINDEX parameters.
|
||||
# http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
|
||||
args.clear if ENV.include?("REQUEST_METHOD")
|
||||
|
||||
options.merge! opt_parser.parse! args
|
||||
options[:config] = ::File.expand_path(options[:config])
|
||||
ENV["RACK_ENV"] = options[:environment]
|
||||
options
|
||||
end
|
||||
options.merge! opt_parser.parse! args
|
||||
options[:config] = ::File.expand_path(options[:config])
|
||||
ENV["RACK_ENV"] = options[:environment]
|
||||
options
|
||||
end
|
||||
</ruby>
|
||||
|
||||
With the +default_options+ set to this:
|
||||
|
||||
<ruby>
|
||||
def default_options
|
||||
{
|
||||
:environment => ENV['RACK_ENV'] || "development",
|
||||
:pid => nil,
|
||||
:Port => 9292,
|
||||
:Host => "0.0.0.0",
|
||||
:AccessLog => [],
|
||||
:config => "config.ru"
|
||||
}
|
||||
end
|
||||
def default_options
|
||||
{
|
||||
:environment => ENV['RACK_ENV'] || "development",
|
||||
:pid => nil,
|
||||
:Port => 9292,
|
||||
:Host => "0.0.0.0",
|
||||
:AccessLog => [],
|
||||
:config => "config.ru"
|
||||
}
|
||||
end
|
||||
</ruby>
|
||||
|
||||
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+
|
||||
|
||||
<ruby>
|
||||
def opt_parser
|
||||
Options.new
|
||||
end
|
||||
def opt_parser
|
||||
Options.new
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The class *is* defined in +Rack::Server+, but is overwritten in +Rails::Server+ to take different arguments. Its +parse!+ method begins like this:
|
||||
|
||||
<ruby>
|
||||
def parse!(args)
|
||||
args, options = args.dup, {}
|
||||
def parse!(args)
|
||||
args, options = args.dup, {}
|
||||
|
||||
opt_parser = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
|
||||
|
@ -362,100 +362,101 @@ h4. +Rails::Server#start+
|
|||
This method is defined like this:
|
||||
|
||||
<ruby>
|
||||
def start
|
||||
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
|
||||
puts "=> Rails #{Rails.version} application starting in #{Rails.env} on http://#{options[:Host]}:#{options[:Port]}"
|
||||
puts "=> Call with -d to detach" unless options[:daemonize]
|
||||
trap(:INT) { exit }
|
||||
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
|
||||
def start
|
||||
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
|
||||
puts "=> Rails #{Rails.version} application starting in #{Rails.env} on http://#{options[:Host]}:#{options[:Port]}"
|
||||
puts "=> Call with -d to detach" unless options[:daemonize]
|
||||
trap(:INT) { exit }
|
||||
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
|
||||
|
||||
#Create required tmp directories if not found
|
||||
%w(cache pids sessions sockets).each do |dir_to_make|
|
||||
FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
|
||||
end
|
||||
|
||||
super
|
||||
ensure
|
||||
# The '-h' option calls exit before @options is set.
|
||||
# If we call 'options' with it unset, we get double help banners.
|
||||
puts 'Exiting' unless @options && options[:daemonize]
|
||||
#Create required tmp directories if not found
|
||||
%w(cache pids sessions sockets).each do |dir_to_make|
|
||||
FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
|
||||
end
|
||||
|
||||
super
|
||||
ensure
|
||||
# The '-h' option calls exit before @options is set.
|
||||
# If we call 'options' with it unset, we get double help banners.
|
||||
puts 'Exiting' unless @options && options[:daemonize]
|
||||
end
|
||||
</ruby>
|
||||
|
||||
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+, +tmp/sessions+ and +tmp/sockets+ directories if they don't already exist prior to calling +super+. The +super+ method will call +Rack::Server.start+ which begins its definition like this:
|
||||
|
||||
<ruby>
|
||||
def start
|
||||
if options[:warn]
|
||||
$-w = true
|
||||
end
|
||||
def start
|
||||
if options[:warn]
|
||||
$-w = true
|
||||
end
|
||||
|
||||
if includes = options[:include]
|
||||
$LOAD_PATH.unshift(*includes)
|
||||
end
|
||||
if includes = options[:include]
|
||||
$LOAD_PATH.unshift(*includes)
|
||||
end
|
||||
|
||||
if library = options[:require]
|
||||
require library
|
||||
end
|
||||
if library = options[:require]
|
||||
require library
|
||||
end
|
||||
|
||||
if options[:debug]
|
||||
$DEBUG = true
|
||||
require 'pp'
|
||||
p options[:server]
|
||||
pp wrapped_app
|
||||
pp app
|
||||
end
|
||||
if options[:debug]
|
||||
$DEBUG = true
|
||||
require 'pp'
|
||||
p options[:server]
|
||||
pp wrapped_app
|
||||
pp app
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
In a Rails application, these options are not set at all and therefore aren't used at all. The first line of code that's executed in this method is a call to this method:
|
||||
|
||||
<ruby>
|
||||
wrapped_app
|
||||
wrapped_app
|
||||
</ruby>
|
||||
|
||||
This method calls another method:
|
||||
|
||||
<ruby>
|
||||
@wrapped_app ||= build_app app
|
||||
@wrapped_app ||= build_app app
|
||||
</ruby>
|
||||
|
||||
Then the +app+ method here is defined like so:
|
||||
|
||||
<ruby>
|
||||
def app
|
||||
@app ||= begin
|
||||
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
|
||||
def app
|
||||
@app ||= begin
|
||||
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
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +options[:config]+ value defaults to +config.ru+ which contains this:
|
||||
|
||||
<ruby>
|
||||
# This file is used by Rack-based servers to start the application.
|
||||
# This file is used by Rack-based servers to start the application.
|
||||
|
||||
require ::File.expand_path('../config/environment', __FILE__)
|
||||
run YourApp::Application
|
||||
require ::File.expand_path('../config/environment', __FILE__)
|
||||
run YourApp::Application
|
||||
</ruby>
|
||||
|
||||
|
||||
The +Rack::Builder.parse_file+ method here takes the content from this +config.ru+ file and parses it using this code:
|
||||
|
||||
<ruby>
|
||||
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
|
||||
app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
|
||||
TOPLEVEL_BINDING, config
|
||||
</ruby>
|
||||
|
||||
The <ruby>initialize</ruby> method 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 chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run:
|
||||
|
||||
<ruby>
|
||||
require ::File.expand_path('../config/environment', __FILE__)
|
||||
require ::File.expand_path('../config/environment', __FILE__)
|
||||
</ruby>
|
||||
|
||||
h4. +config/environment.rb+
|
||||
|
@ -475,7 +476,7 @@ h3. Loading Rails
|
|||
The next line in +config/application.rb+ is:
|
||||
|
||||
<ruby>
|
||||
require 'rails/all'
|
||||
require 'rails/all'
|
||||
</ruby>
|
||||
|
||||
h4. +railties/lib/rails/all.rb+
|
||||
|
@ -483,20 +484,20 @@ h4. +railties/lib/rails/all.rb+
|
|||
This file is responsible for requiring all the individual parts of Rails like so:
|
||||
|
||||
<ruby>
|
||||
require "rails"
|
||||
require "rails"
|
||||
|
||||
%w(
|
||||
%w(
|
||||
active_record
|
||||
action_controller
|
||||
action_mailer
|
||||
active_resource
|
||||
rails/test_unit
|
||||
).each do |framework|
|
||||
begin
|
||||
require "#{framework}/railtie"
|
||||
rescue LoadError
|
||||
end
|
||||
).each do |framework|
|
||||
begin
|
||||
require "#{framework}/railtie"
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
First off the line is the +rails+ require itself.
|
||||
|
@ -518,9 +519,9 @@ h4. +active_support/core_ext/kernel/reporting.rb+
|
|||
This is the first of the many Active Support core extensions that come with Rails. This one in particular defines methods in the +Kernel+ module which is mixed in to the +Object+ class so the methods are available on +main+ and can therefore be called like this:
|
||||
|
||||
<ruby>
|
||||
silence_warnings do
|
||||
# some code
|
||||
end
|
||||
silence_warnings do
|
||||
# some code
|
||||
end
|
||||
</ruby>
|
||||
|
||||
These methods can be used to silence STDERR responses and the +silence_stream+ allows you to also silence other streams. Additionally, this mixin allows you to suppress exceptions and capture streams. For more information see the "Silencing Warnings, Streams, and Exceptions":http://guides.rubyonrails.org/active_support_core_extensions.html#silencing-warnings-streams-and-exceptions section from the Active Support Core Extensions Guide.
|
||||
|
@ -635,14 +636,14 @@ h4. +railties/lib/rails/rack.rb+
|
|||
The final file to be loaded by +railties/lib/rails/configuration.rb+ is +rails/rack+ which defines some simple autoloads:
|
||||
|
||||
<ruby>
|
||||
module Rails
|
||||
module Rack
|
||||
autoload :Debugger, "rails/rack/debugger"
|
||||
autoload :Logger, "rails/rack/logger"
|
||||
autoload :LogTailer, "rails/rack/log_tailer"
|
||||
autoload :Static, "rails/rack/static"
|
||||
end
|
||||
module Rails
|
||||
module Rack
|
||||
autoload :Debugger, "rails/rack/debugger"
|
||||
autoload :Logger, "rails/rack/logger"
|
||||
autoload :LogTailer, "rails/rack/log_tailer"
|
||||
autoload :Static, "rails/rack/static"
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Once this file is finished loading, then the +Rails::Configuration+ class is initialized. This completes the loading of +railties/lib/rails/configuration.rb+ and now we jump back to the loading of +railties/lib/rails/railtie.rb+, where the next file loaded is +active_support/inflector+.
|
||||
|
@ -652,12 +653,12 @@ h4. +activesupport/lib/active_support/inflector.rb+
|
|||
+active_support/inflector.rb+ requires a series of file which are responsible for setting up the basics for knowing how to pluralize and singularize words. These files are:
|
||||
|
||||
<ruby>
|
||||
require 'active_support/inflector/inflections'
|
||||
require 'active_support/inflector/transliterate'
|
||||
require 'active_support/inflector/methods'
|
||||
require 'active_support/inflector/inflections'
|
||||
require 'active_support/inflector/transliterate'
|
||||
require 'active_support/inflector/methods'
|
||||
|
||||
require 'active_support/inflections'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
require 'active_support/inflections'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
</ruby>
|
||||
|
||||
The +active_support/inflector/methods+ file has already been required by +active_support/autoload+ and so won't be loaded again here.
|
||||
|
@ -721,22 +722,22 @@ h4. +activesupport/lib/active_support/i18n_railtie.rb+
|
|||
This file is the first file that sets up configuration with these lines inside the class:
|
||||
|
||||
<ruby>
|
||||
class Railtie < Rails::Railtie
|
||||
config.i18n = ActiveSupport::OrderedOptions.new
|
||||
config.i18n.railties_load_path = []
|
||||
config.i18n.load_path = []
|
||||
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
||||
class Railtie < Rails::Railtie
|
||||
config.i18n = ActiveSupport::OrderedOptions.new
|
||||
config.i18n.railties_load_path = []
|
||||
config.i18n.load_path = []
|
||||
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
||||
</ruby>
|
||||
|
||||
By inheriting from +Rails::Railtie+ the +Rails::Railtie#inherited+ method is called:
|
||||
|
||||
<ruby>
|
||||
def inherited(base)
|
||||
unless base.abstract_railtie?
|
||||
base.send(:include, Railtie::Configurable)
|
||||
subclasses << base
|
||||
end
|
||||
def inherited(base)
|
||||
unless base.abstract_railtie?
|
||||
base.send(:include, Railtie::Configurable)
|
||||
subclasses << base
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This first checks if the Railtie that's inheriting it is a component of Rails itself:
|
||||
|
@ -763,15 +764,15 @@ end
|
|||
The +config+ method used at the top of +I18n::Railtie+ is defined on +Rails::Railtie+ and is defined like this:
|
||||
|
||||
<ruby>
|
||||
def config
|
||||
@config ||= Railtie::Configuration.new
|
||||
end
|
||||
def config
|
||||
@config ||= Railtie::Configuration.new
|
||||
end
|
||||
</ruby>
|
||||
|
||||
At this point, that +Railtie::Configuration+ constant is automatically loaded which causes the +rails/railties/configuration+ file to be loaded. The line for this is this particular line in +railties/lib/rails/railtie.rb+:
|
||||
|
||||
<ruby>
|
||||
autoload :Configuration, "rails/railtie/configuration"
|
||||
autoload :Configuration, "rails/railtie/configuration"
|
||||
</ruby>
|
||||
|
||||
h4. +railties/lib/rails/railtie/configuration.rb+
|
||||
|
@ -781,15 +782,15 @@ This file begins with a require out to +rails/configuration+ which has already b
|
|||
This file defines the +Rails::Railtie::Configuration+ class which is responsible for providing a way to easily configure railties and it's the +initialize+ method here which is called by the +config+ method back in the +i18n_railtie.rb+ file. The methods on this object don't exist, and so are rescued by the +method_missing+ defined further down in +configuration.rb+:
|
||||
|
||||
<ruby>
|
||||
def method_missing(name, *args, &blk)
|
||||
if name.to_s =~ /=$/
|
||||
@@options[$`.to_sym] = args.first
|
||||
elsif @@options.key?(name)
|
||||
@@options[name]
|
||||
else
|
||||
super
|
||||
end
|
||||
def method_missing(name, *args, &blk)
|
||||
if name.to_s =~ /=$/
|
||||
@@options[$`.to_sym] = args.first
|
||||
elsif @@options.key?(name)
|
||||
@@options[name]
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
So therefore when an option is referred to it simply stores the value as the key if it's used in a setter context, or retrieves it if used in a getter context. Nothing fancy going on there.
|
||||
|
@ -799,21 +800,21 @@ h4. Back to +activesupport/lib/active_support/i18n_railtie.rb+
|
|||
After the configuration method the +reloader+ method is defined, and then the first of of Railties' initializers is defined: +i18n.callbacks+.
|
||||
|
||||
<ruby>
|
||||
initializer "i18n.callbacks" do
|
||||
ActionDispatch::Reloader.to_prepare do
|
||||
I18n::Railtie.reloader.execute_if_updated
|
||||
end
|
||||
initializer "i18n.callbacks" do
|
||||
ActionDispatch::Reloader.to_prepare do
|
||||
I18n::Railtie.reloader.execute_if_updated
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +initializer+ method (from the +Rails::Initializable+ module) here doesn't run the block, but rather stores it to be run later on:
|
||||
|
||||
<ruby>
|
||||
def initializer(name, opts = {}, &blk)
|
||||
raise ArgumentError, "A block must be passed when defining an initializer" unless blk
|
||||
opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
|
||||
initializers << Initializer.new(name, nil, opts, &blk)
|
||||
end
|
||||
def initializer(name, opts = {}, &blk)
|
||||
raise ArgumentError, "A block must be passed when defining an initializer" unless blk
|
||||
opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
|
||||
initializers << Initializer.new(name, nil, opts, &blk)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
An initializer can be configured to run before or after another initializer, which we'll see a couple of times throughout this initialization process. Anything that inherits from +Rails::Railtie+ may also make use of the +initializer+ method, something which is covered in the "Configuration guide":[http://ryanbigg.com/guides/configuring.html#rails-railtie-initializer].
|
||||
|
@ -821,25 +822,25 @@ An initializer can be configured to run before or after another initializer, whi
|
|||
The +Initializer+ class here is defined within the +Rails::Initializable+ module and its +initialize+ method is defined to just set up a couple of variables:
|
||||
|
||||
<ruby>
|
||||
def initialize(name, context, options, &block)
|
||||
@name, @context, @options, @block = name, context, options, block
|
||||
end
|
||||
def initialize(name, context, options, &block)
|
||||
@name, @context, @options, @block = name, context, options, block
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Once this +initialize+ method is finished, the object is added to the object the +initializers+ method returns:
|
||||
|
||||
<ruby>
|
||||
def initializers
|
||||
@initializers ||= self.class.initializers_for(self)
|
||||
end
|
||||
def initializers
|
||||
@initializers ||= self.class.initializers_for(self)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
If +@initializers+ isn't set (which it won't be at this point), the +intializers_for+ method will be called for this class.
|
||||
|
||||
<ruby>
|
||||
def initializers_for(binding)
|
||||
Collection.new(initializers_chain.map { |i| i.bind(binding) })
|
||||
end
|
||||
def initializers_for(binding)
|
||||
Collection.new(initializers_chain.map { |i| i.bind(binding) })
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +Collection+ class in +railties/lib/rails/initializable.rb+ inherits from +Array+ and includes the +TSort+ module which is used to sort out the order of the initializers based on the order they are placed in.
|
||||
|
@ -847,22 +848,22 @@ The +Collection+ class in +railties/lib/rails/initializable.rb+ inherits from +A
|
|||
The +initializers_chain+ method referenced in the +initializers_for+ method is defined like this:
|
||||
|
||||
<rub>
|
||||
def initializers_chain
|
||||
initializers = Collection.new
|
||||
ancestors.reverse_each do | klass |
|
||||
next unless klass.respond_to?(:initializers)
|
||||
initializers = initializers + klass.initializers
|
||||
end
|
||||
initializers
|
||||
def initializers_chain
|
||||
initializers = Collection.new
|
||||
ancestors.reverse_each do | klass |
|
||||
next unless klass.respond_to?(:initializers)
|
||||
initializers = initializers + klass.initializers
|
||||
end
|
||||
initializers
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This method collects the initializers from the ancestors of this class and adds them to a new +Collection+ object using the <tt>+</tt> method which is defined like this for the <tt>Collection</tt> class:
|
||||
|
||||
<ruby>
|
||||
def +(other)
|
||||
Collection.new(to_a + other.to_a)
|
||||
end
|
||||
def +(other)
|
||||
Collection.new(to_a + other.to_a)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
So this <tt>+</tt> method is overridden to return a new collection comprising of the existing collection as an array and then using the <tt>Array#+</tt> method combines these two collections, returning a "super" +Collection+ object. In this case, the only initializer that's going to be in this new +Collection+ object is the +i18n.callbacks+ initializer.
|
||||
|
@ -870,34 +871,34 @@ So this <tt>+</tt> method is overridden to return a new collection comprising of
|
|||
The next method to be called after this +initializer+ method is the +after_initialize+ method on the +config+ object, which is defined like this:
|
||||
|
||||
<ruby>
|
||||
def after_initialize(&block)
|
||||
ActiveSupport.on_load(:after_initialize, :yield => true, &block)
|
||||
end
|
||||
def after_initialize(&block)
|
||||
ActiveSupport.on_load(:after_initialize, :yield => true, &block)
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +on_load+ method here is provided by the +active_support/lazy_load_hooks+ file which was required earlier and is defined like this:
|
||||
|
||||
<ruby>
|
||||
def self.on_load(name, options = {}, &block)
|
||||
if base = @loaded[name]
|
||||
execute_hook(base, options, block)
|
||||
else
|
||||
@load_hooks[name] << [block, options]
|
||||
end
|
||||
def self.on_load(name, options = {}, &block)
|
||||
if base = @loaded[name]
|
||||
execute_hook(base, options, block)
|
||||
else
|
||||
@load_hooks[name] << [block, options]
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
The +@loaded+ variable here is a hash containing elements representing the different components of Rails that have been loaded at this stage. Currently, this hash is empty. So the +else+ is executed here, using the +@load_hooks+ variable defined in +active_support/lazy_load_hooks+:
|
||||
|
||||
<ruby>
|
||||
@load_hooks = Hash.new {|h,k| h[k] = [] }
|
||||
@load_hooks = Hash.new {|h,k| h[k] = [] }
|
||||
</ruby>
|
||||
|
||||
This defines a new hash which has keys that default to empty arrays. This saves Rails from having to do something like this instead:
|
||||
|
||||
<ruby>
|
||||
@load_hooks[name] = []
|
||||
@load_hooks[name] << [block, options]
|
||||
@load_hooks[name] = []
|
||||
@load_hooks[name] << [block, options]
|
||||
</ruby>
|
||||
|
||||
The value added to this array here consists of the block and options passed to +after_initialize+.
|
||||
|
@ -929,11 +930,11 @@ h4. +activesupport/lib/action_dispatch.rb+
|
|||
This file attempts to locate the +active_support+ and +active_model+ libraries by looking a couple of directories back from the current file and then adds the +active_support+ and +active_model+ +lib+ directories to the load path, but only if they aren't already, which they are.
|
||||
|
||||
<ruby>
|
||||
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
|
||||
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
|
||||
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
|
||||
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
|
||||
|
||||
activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
|
||||
$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
|
||||
activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
|
||||
$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
|
||||
</ruby>
|
||||
|
||||
In effect, these lines only define the +activesupport_path+ and +activemodel_path+ variables and nothing more.
|
||||
|
@ -941,23 +942,23 @@ In effect, these lines only define the +activesupport_path+ and +activemodel_pat
|
|||
The next two requires in this file are already done, so they are not run:
|
||||
|
||||
<ruby>
|
||||
require 'active_support'
|
||||
require 'active_support/dependencies/autoload'
|
||||
require 'active_support'
|
||||
require 'active_support/dependencies/autoload'
|
||||
</ruby>
|
||||
|
||||
The following require is to +action_pack+ (+activesupport/lib/action_pack.rb+) which has a 22-line copyright notice at the top of it and ends in a simple require to +action_pack/version+. This file, like other +version.rb+ files before it, defines the +ActionPack::VERSION+ constant:
|
||||
|
||||
<ruby>
|
||||
module ActionPack
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
module ActionPack
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Once +action_pack+ is finished, then +active_model+ is required.
|
||||
|
@ -967,16 +968,16 @@ h4. +activemodel/lib/active_model.rb+
|
|||
This file makes a require to +active_model/version+ which defines the version for Active Model:
|
||||
|
||||
<ruby>
|
||||
module ActiveModel
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
module ActiveModel
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Once the +version.rb+ file is loaded, the +ActiveModel+ module has its autoloaded constants defined as well as a sub-module called +ActiveModel::Serializers+ which has autoloads of its own. When the +ActiveModel+ module is closed the +active_support/i18n+ file is required.
|
||||
|
@ -986,15 +987,15 @@ h4. +activesupport/lib/active_support/i18n.rb+
|
|||
This is where the +i18n+ gem is required and first configured:
|
||||
|
||||
<ruby>
|
||||
begin
|
||||
require 'i18n'
|
||||
require 'active_support/lazy_load_hooks'
|
||||
rescue LoadError => e
|
||||
$stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
|
||||
raise e
|
||||
end
|
||||
begin
|
||||
require 'i18n'
|
||||
require 'active_support/lazy_load_hooks'
|
||||
rescue LoadError => e
|
||||
$stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
|
||||
raise e
|
||||
end
|
||||
|
||||
I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
|
||||
I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
|
||||
</ruby>
|
||||
|
||||
In effect, the +I18n+ module first defined by +i18n_railtie+ is extended by the +i18n+ gem, rather than the other way around. This has no ill effect. They both work on the same way.
|
||||
|
@ -1012,9 +1013,9 @@ h4. Back to +activesupport/lib/action_dispatch.rb+
|
|||
The remainder of this file requires the +rack+ file from the Rack gem which defines the +Rack+ module. After +rack+, there's autoloads defined for the +Rack+, +ActionDispatch+, +ActionDispatch::Http+, +ActionDispatch::Session+. A new method called +autoload_under+ is used here, and this simply prefixes the files where the modules are autoloaded from with the path specified. For example here:
|
||||
|
||||
<ruby>
|
||||
autoload_under 'testing' do
|
||||
autoload :Assertions
|
||||
...
|
||||
autoload_under 'testing' do
|
||||
autoload :Assertions
|
||||
...
|
||||
</ruby>
|
||||
|
||||
The +Assertions+ module is in the +action_dispatch/testing+ folder rather than simply +action_dispatch+.
|
||||
|
@ -1046,25 +1047,25 @@ This file begins by detecting if the +lib+ directories of +active_support+ and +
|
|||
The first three requires have already been done by other files and so aren't loaded here, but the 4th require, the one to +arel+ will require the file provided by the Arel gem, which defines the +Arel+ module.
|
||||
|
||||
<ruby>
|
||||
require 'active_support'
|
||||
require 'active_support/i18n'
|
||||
require 'active_model'
|
||||
require 'arel'
|
||||
require 'active_support'
|
||||
require 'active_support/i18n'
|
||||
require 'active_model'
|
||||
require 'arel'
|
||||
</ruby>
|
||||
|
||||
The 5th require in this file is one to +active_record/version+ which defines the +ActiveRecord::VERSION+ constant:
|
||||
|
||||
<ruby>
|
||||
module ActiveRecord
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
module ActiveRecord
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 3
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
PRE = "beta"
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
end
|
||||
</ruby>
|
||||
|
||||
Once these requires are finished, the base for the +ActiveRecord+ module is defined along with its autoloads.
|
||||
|
@ -1072,9 +1073,9 @@ Once these requires are finished, the base for the +ActiveRecord+ module is defi
|
|||
Near the end of the file, we see this line:
|
||||
|
||||
<ruby>
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
Arel::Table.engine = self
|
||||
end
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
Arel::Table.engine = self
|
||||
end
|
||||
</ruby>
|
||||
|
||||
This will set the engine for +Arel::Table+ to be +ActiveRecord::Base+.
|
||||
|
@ -1082,7 +1083,7 @@ This will set the engine for +Arel::Table+ to be +ActiveRecord::Base+.
|
|||
The file then finishes with this line:
|
||||
|
||||
<ruby>
|
||||
I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
|
||||
I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
|
||||
</ruby>
|
||||
|
||||
This will add the translations from +activerecord/lib/active_record/locale/en.yml+ to the load path for +I18n+, with this file being parsed when all the translations are loaded.
|
||||
|
@ -1092,8 +1093,8 @@ h4. Back to +activerecord/lib/active_record/railtie.rb+
|
|||
The next two <tt>require</tt>s in this file aren't run because their files are already required, with +rails+ being required by +rails/all+ and +active_model/railtie+ being required from +action_dispatch+.
|
||||
|
||||
<ruby>
|
||||
require "rails"
|
||||
require "active_model/railtie"
|
||||
require "rails"
|
||||
require "active_model/railtie"
|
||||
</ruby>
|
||||
|
||||
The next +require+ in this file is to +action_controller/railtie+.
|
||||
|
@ -1103,9 +1104,9 @@ h4. +actionpack/lib/action_controller/railtie.rb+
|
|||
This file begins with a couple more requires to files that have already been loaded:
|
||||
|
||||
<ruby>
|
||||
require "rails"
|
||||
require "action_controller"
|
||||
require "action_dispatch/railtie"
|
||||
require "rails"
|
||||
require "action_controller"
|
||||
require "action_dispatch/railtie"
|
||||
</ruby>
|
||||
|
||||
However the require after these is to a file that hasn't yet been loaded, +action_view/railtie+, which begins by requiring +action_view+.
|
||||
|
|
Loading…
Reference in a new issue