rails 4.0.0 → 4.2.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +30 -23
  3. data/guides/CHANGELOG.md +108 -6
  4. data/guides/Rakefile +21 -6
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/edge_badge.png +0 -0
  7. data/guides/assets/images/feature_tile.gif +0 -0
  8. data/guides/assets/images/footer_tile.gif +0 -0
  9. data/guides/assets/images/fxn.png +0 -0
  10. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  11. data/guides/assets/images/getting_started/challenge.png +0 -0
  12. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  13. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  14. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  15. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  16. data/guides/assets/images/getting_started/new_article.png +0 -0
  17. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  18. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  19. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  20. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  22. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  23. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  24. data/guides/assets/images/header_tile.gif +0 -0
  25. data/guides/assets/images/icons/README +1 -1
  26. data/guides/assets/images/icons/callouts/11.png +0 -0
  27. data/guides/assets/images/icons/callouts/12.png +0 -0
  28. data/guides/assets/images/icons/callouts/13.png +0 -0
  29. data/guides/assets/images/icons/callouts/15.png +0 -0
  30. data/guides/assets/images/icons/caution.png +0 -0
  31. data/guides/assets/images/icons/example.png +0 -0
  32. data/guides/assets/images/radar.png +0 -0
  33. data/guides/assets/images/rails4_features.png +0 -0
  34. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  35. data/guides/assets/images/vijaydev.jpg +0 -0
  36. data/guides/assets/javascripts/guides.js +36 -34
  37. data/guides/assets/stylesheets/main.css +6 -2
  38. data/guides/assets/stylesheets/print.css +1 -1
  39. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  40. data/guides/bug_report_templates/action_controller_master.rb +54 -0
  41. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  42. data/guides/bug_report_templates/active_record_master.rb +3 -2
  43. data/guides/bug_report_templates/generic_gem.rb +15 -0
  44. data/guides/bug_report_templates/generic_master.rb +26 -0
  45. data/guides/rails_guides.rb +23 -4
  46. data/guides/rails_guides/generator.rb +1 -1
  47. data/guides/rails_guides/helpers.rb +4 -2
  48. data/guides/rails_guides/levenshtein.rb +27 -21
  49. data/guides/rails_guides/markdown.rb +11 -7
  50. data/guides/rails_guides/markdown/renderer.rb +1 -1
  51. data/guides/source/2_2_release_notes.md +3 -3
  52. data/guides/source/2_3_release_notes.md +12 -12
  53. data/guides/source/3_0_release_notes.md +10 -13
  54. data/guides/source/3_1_release_notes.md +7 -4
  55. data/guides/source/3_2_release_notes.md +17 -14
  56. data/guides/source/4_0_release_notes.md +110 -54
  57. data/guides/source/4_1_release_notes.md +730 -0
  58. data/guides/source/4_2_release_notes.md +877 -0
  59. data/guides/source/_license.html.erb +1 -1
  60. data/guides/source/_welcome.html.erb +6 -2
  61. data/guides/source/action_controller_overview.md +223 -57
  62. data/guides/source/action_mailer_basics.md +129 -76
  63. data/guides/source/action_view_overview.md +247 -246
  64. data/guides/source/active_job_basics.md +339 -0
  65. data/guides/source/active_model_basics.md +374 -20
  66. data/guides/source/active_record_basics.md +46 -45
  67. data/guides/source/active_record_callbacks.md +83 -28
  68. data/guides/source/{migrations.md → active_record_migrations.md} +191 -275
  69. data/guides/source/active_record_postgresql.md +433 -0
  70. data/guides/source/active_record_querying.md +382 -300
  71. data/guides/source/active_record_validations.md +64 -55
  72. data/guides/source/active_support_core_extensions.md +229 -187
  73. data/guides/source/active_support_instrumentation.md +23 -22
  74. data/guides/source/api_documentation_guidelines.md +167 -15
  75. data/guides/source/asset_pipeline.md +768 -294
  76. data/guides/source/association_basics.md +188 -96
  77. data/guides/source/autoloading_and_reloading_constants.md +1311 -0
  78. data/guides/source/caching_with_rails.md +45 -11
  79. data/guides/source/command_line.md +96 -65
  80. data/guides/source/configuring.md +404 -70
  81. data/guides/source/contributing_to_ruby_on_rails.md +270 -130
  82. data/guides/source/credits.html.erb +7 -3
  83. data/guides/source/debugging_rails_applications.md +471 -284
  84. data/guides/source/development_dependencies_install.md +115 -21
  85. data/guides/source/documents.yaml +31 -9
  86. data/guides/source/engines.md +737 -291
  87. data/guides/source/form_helpers.md +137 -89
  88. data/guides/source/generators.md +60 -28
  89. data/guides/source/getting_started.md +1007 -596
  90. data/guides/source/i18n.md +178 -96
  91. data/guides/source/index.html.erb +2 -1
  92. data/guides/source/initialization.md +248 -104
  93. data/guides/source/kindle/toc.html.erb +1 -1
  94. data/guides/source/layout.html.erb +14 -22
  95. data/guides/source/layouts_and_rendering.md +78 -46
  96. data/guides/source/maintenance_policy.md +78 -0
  97. data/guides/source/nested_model_forms.md +10 -7
  98. data/guides/source/plugins.md +66 -57
  99. data/guides/source/rails_application_templates.md +49 -12
  100. data/guides/source/rails_on_rack.md +50 -60
  101. data/guides/source/routing.md +190 -139
  102. data/guides/source/ruby_on_rails_guides_guidelines.md +12 -13
  103. data/guides/source/security.md +134 -83
  104. data/guides/source/testing.md +322 -200
  105. data/guides/source/upgrading_ruby_on_rails.md +834 -37
  106. data/guides/source/working_with_javascript_in_rails.md +36 -26
  107. data/guides/w3c_validator.rb +2 -0
  108. metadata +93 -116
  109. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  110. data/guides/assets/images/getting_started/new_post.png +0 -0
  111. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  112. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  113. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  114. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  115. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  116. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  117. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  118. data/guides/code/getting_started/Gemfile +0 -43
  119. data/guides/code/getting_started/Gemfile.lock +0 -150
  120. data/guides/code/getting_started/README.rdoc +0 -28
  121. data/guides/code/getting_started/Rakefile +0 -6
  122. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -16
  123. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  124. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  125. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  126. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  127. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  128. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  129. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  130. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  131. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -17
  132. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -47
  133. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  134. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  135. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  136. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  137. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  138. data/guides/code/getting_started/app/models/comment.rb +0 -3
  139. data/guides/code/getting_started/app/models/post.rb +0 -7
  140. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  141. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  142. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  143. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  144. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  145. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  146. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  147. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  148. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -3
  149. data/guides/code/getting_started/bin/bundle +0 -4
  150. data/guides/code/getting_started/bin/rails +0 -4
  151. data/guides/code/getting_started/bin/rake +0 -4
  152. data/guides/code/getting_started/config.ru +0 -4
  153. data/guides/code/getting_started/config/application.rb +0 -18
  154. data/guides/code/getting_started/config/boot.rb +0 -4
  155. data/guides/code/getting_started/config/database.yml +0 -25
  156. data/guides/code/getting_started/config/environment.rb +0 -5
  157. data/guides/code/getting_started/config/environments/development.rb +0 -30
  158. data/guides/code/getting_started/config/environments/production.rb +0 -80
  159. data/guides/code/getting_started/config/environments/test.rb +0 -36
  160. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  161. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  162. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  163. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  164. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  165. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  166. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  167. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  168. data/guides/code/getting_started/config/locales/en.yml +0 -23
  169. data/guides/code/getting_started/config/routes.rb +0 -7
  170. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  171. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  172. data/guides/code/getting_started/db/schema.rb +0 -33
  173. data/guides/code/getting_started/db/seeds.rb +0 -7
  174. data/guides/code/getting_started/public/404.html +0 -58
  175. data/guides/code/getting_started/public/422.html +0 -58
  176. data/guides/code/getting_started/public/500.html +0 -57
  177. data/guides/code/getting_started/public/favicon.ico +0 -0
  178. data/guides/code/getting_started/public/robots.txt +0 -5
  179. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  180. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  181. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  182. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  183. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  184. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  185. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  186. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  187. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  188. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  189. data/guides/code/getting_started/test/test_helper.rb +0 -15
  190. data/guides/source/kindle/KINDLE.md +0 -26
@@ -9,6 +9,7 @@ Ruby on Rails Guides
9
9
  <% content_for :index_section do %>
10
10
  <div id="subCol">
11
11
  <dl>
12
+ <dt></dt>
12
13
  <dd class="kindle">Rails Guides are also available for <%= link_to 'Kindle', @mobi %>.</dd>
13
14
  <dd class="work-in-progress">Guides marked with this icon are currently being worked on and will not be available in the Guides Index menu. While still useful, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections.</dd>
14
15
  </dl>
@@ -19,7 +20,7 @@ Ruby on Rails Guides
19
20
  <h3><%= section['name'] %></h3>
20
21
  <dl>
21
22
  <% section['documents'].each do |document| %>
22
- <%= guide(document['name'], document['url'], :work_in_progress => document['work_in_progress']) do %>
23
+ <%= guide(document['name'], document['url'], work_in_progress: document['work_in_progress']) do %>
23
24
  <p><%= document['description'] %></p>
24
25
  <% end %>
25
26
  <% end %>
@@ -7,14 +7,17 @@ as of Rails 4. It is an extremely in-depth guide and recommended for advanced Ra
7
7
  After reading this guide, you will know:
8
8
 
9
9
  * How to use `rails server`.
10
+ * The timeline of Rails' initialization sequence.
11
+ * Where different files are required by the boot sequence.
12
+ * How the Rails::Server interface is defined and used.
10
13
 
11
14
  --------------------------------------------------------------------------------
12
15
 
13
16
  This guide goes through every method call that is
14
17
  required to boot up the Ruby on Rails stack for a default Rails 4
15
18
  application, explaining each part in detail along the way. For this
16
- guide, we will be focusing on what happens when you execute +rails
17
- server+ to boot your app.
19
+ guide, we will be focusing on what happens when you execute `rails server`
20
+ to boot your app.
18
21
 
19
22
  NOTE: Paths in this guide are relative to Rails or a Rails application unless otherwise specified.
20
23
 
@@ -26,9 +29,42 @@ quickly.
26
29
  Launch!
27
30
  -------
28
31
 
29
- Now we finally boot and initialize the app. It all starts with your app's
30
- `bin/rails` executable. A Rails application is usually started by running
31
- `rails console` or `rails server`.
32
+ Let's start to boot and initialize the app. A Rails application is usually
33
+ started by running `rails console` or `rails server`.
34
+
35
+ ### `railties/bin/rails`
36
+
37
+ The `rails` in the command `rails server` is a ruby executable in your load
38
+ path. This executable contains the following lines:
39
+
40
+ ```ruby
41
+ version = ">= 0"
42
+ load Gem.bin_path('railties', 'rails', version)
43
+ ```
44
+
45
+ If you try out this command in a Rails console, you would see that this loads
46
+ `railties/bin/rails`. A part of the file `railties/bin/rails.rb` has the
47
+ following code:
48
+
49
+ ```ruby
50
+ require "rails/cli"
51
+ ```
52
+
53
+ The file `railties/lib/rails/cli` in turn calls
54
+ `Rails::AppRailsLoader.exec_app_rails`.
55
+
56
+ ### `railties/lib/rails/app_rails_loader.rb`
57
+
58
+ The primary goal of the function `exec_app_rails` is to execute your app's
59
+ `bin/rails`. If the current directory does not have a `bin/rails`, it will
60
+ navigate upwards until it finds a `bin/rails` executable. Thus one can invoke a
61
+ `rails` command from anywhere inside a rails application.
62
+
63
+ For `rails server` the equivalent of the following command is executed:
64
+
65
+ ```bash
66
+ $ exec ruby bin/rails server
67
+ ```
32
68
 
33
69
  ### `bin/rails`
34
70
 
@@ -36,8 +72,8 @@ This file is as follows:
36
72
 
37
73
  ```ruby
38
74
  #!/usr/bin/env ruby
39
- APP_PATH = File.expand_path('../../config/application', __FILE__)
40
- require File.expand_path('../../config/boot', __FILE__)
75
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
76
+ require_relative '../config/boot'
41
77
  require 'rails/commands'
42
78
  ```
43
79
 
@@ -51,19 +87,20 @@ The `APP_PATH` constant will be used later in `rails/commands`. The `config/boot
51
87
  # Set up gems listed in the Gemfile.
52
88
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
53
89
 
54
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
90
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
55
91
  ```
56
92
 
57
93
  In a standard Rails application, there's a `Gemfile` which declares all
58
94
  dependencies of the application. `config/boot.rb` sets
59
95
  `ENV['BUNDLE_GEMFILE']` to the location of this file. If the Gemfile
60
- exists, `bundler/setup` is then required.
96
+ exists, then `bundler/setup` is required. The require is used by Bundler to
97
+ configure the load path for your Gemfile's dependencies.
61
98
 
62
99
  A standard Rails application depends on several gems, specifically:
63
100
 
64
- * abstract
65
101
  * actionmailer
66
102
  * actionpack
103
+ * actionview
67
104
  * activemodel
68
105
  * activerecord
69
106
  * activesupport
@@ -74,7 +111,6 @@ A standard Rails application depends on several gems, specifically:
74
111
  * i18n
75
112
  * mail
76
113
  * mime-types
77
- * polyglot
78
114
  * rack
79
115
  * rack-cache
80
116
  * rack-mount
@@ -82,14 +118,15 @@ A standard Rails application depends on several gems, specifically:
82
118
  * rails
83
119
  * railties
84
120
  * rake
85
- * sqlite3-ruby
121
+ * sqlite3
86
122
  * thor
87
- * treetop
88
123
  * tzinfo
89
124
 
90
125
  ### `rails/commands.rb`
91
126
 
92
- 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:
127
+ Once `config/boot.rb` has finished, the next file that is required is
128
+ `rails/commands`, which helps in expanding aliases. In the current case, the
129
+ `ARGV` array simply contains `server` which will be passed over:
93
130
 
94
131
  ```ruby
95
132
  ARGV << '--help' if ARGV.empty?
@@ -105,21 +142,48 @@ aliases = {
105
142
 
106
143
  command = ARGV.shift
107
144
  command = aliases[command] || command
145
+
146
+ require 'rails/commands/commands_tasks'
147
+
148
+ Rails::CommandsTasks.new(ARGV).run_command!(command)
108
149
  ```
109
150
 
110
151
  TIP: As you can see, an empty ARGV list will make Rails show the help
111
152
  snippet.
112
153
 
113
- If we used `s` 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:
154
+ If we had used `s` rather than `server`, Rails would have used the `aliases`
155
+ defined here to find the matching command.
156
+
157
+ ### `rails/commands/command_tasks.rb`
158
+
159
+ When one types an incorrect rails command, the `run_command` is responsible for
160
+ throwing an error message. If the command is valid, a method of the same name
161
+ is called.
114
162
 
115
163
  ```ruby
116
- when 'server'
117
- # Change to the application's path if there is no config.ru file in current dir.
118
- # This allows us to run `rails server` from other directories, but still get
119
- # the main config.ru and properly set the tmp directory.
120
- Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
164
+ COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole application runner new version help)
165
+
166
+ def run_command!(command)
167
+ command = parse_command(command)
168
+ if COMMAND_WHITELIST.include?(command)
169
+ send(command)
170
+ else
171
+ write_error_message(command)
172
+ end
173
+ end
174
+ ```
175
+
176
+ With the `server` command, Rails will further run the following code:
177
+
178
+ ```ruby
179
+ def set_application_directory!
180
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
181
+ end
182
+
183
+ def server
184
+ set_application_directory!
185
+ require_command!("server")
121
186
 
122
- require 'rails/commands/server'
123
187
  Rails::Server.new.tap do |server|
124
188
  # We need to require application after the server sets environment,
125
189
  # otherwise the --environment option given to the server won't propagate.
@@ -127,14 +191,23 @@ when 'server'
127
191
  Dir.chdir(Rails.application.root)
128
192
  server.start
129
193
  end
194
+ end
195
+
196
+ def require_command!(command)
197
+ require "rails/commands/#{command}"
198
+ end
130
199
  ```
131
200
 
132
- 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.
201
+ This file will change into the Rails root directory (a path two directories up
202
+ from `APP_PATH` which points at `config/application.rb`), but only if the
203
+ `config.ru` file isn't found. This then requires `rails/commands/server` which
204
+ sets up the `Rails::Server` class.
133
205
 
134
206
  ```ruby
135
207
  require 'fileutils'
136
208
  require 'optparse'
137
209
  require 'action_dispatch'
210
+ require 'rails'
138
211
 
139
212
  module Rails
140
213
  class Server < ::Rack::Server
@@ -198,10 +271,10 @@ def parse_options(args)
198
271
  options = default_options
199
272
 
200
273
  # Don't evaluate CGI ISINDEX parameters.
201
- # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
274
+ # http://www.meb.uni-bonn.de/docs/cgi/cl.html
202
275
  args.clear if ENV.include?("REQUEST_METHOD")
203
276
 
204
- options.merge! opt_parser.parse! args
277
+ options.merge! opt_parser.parse!(args)
205
278
  options[:config] = ::File.expand_path(options[:config])
206
279
  ENV["RACK_ENV"] = options[:environment]
207
280
  options
@@ -212,18 +285,21 @@ With the `default_options` set to this:
212
285
 
213
286
  ```ruby
214
287
  def default_options
288
+ environment = ENV['RACK_ENV'] || 'development'
289
+ default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
290
+
215
291
  {
216
- :environment => ENV['RACK_ENV'] || "development",
292
+ :environment => environment,
217
293
  :pid => nil,
218
294
  :Port => 9292,
219
- :Host => "0.0.0.0",
295
+ :Host => default_host,
220
296
  :AccessLog => [],
221
297
  :config => "config.ru"
222
298
  }
223
299
  end
224
300
  ```
225
301
 
226
- 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`
302
+ 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`:
227
303
 
228
304
  ```ruby
229
305
  def opt_parser
@@ -251,43 +327,50 @@ set earlier) is required.
251
327
 
252
328
  ### `config/application`
253
329
 
254
- When `require APP_PATH` is executed, `config/application.rb` is loaded.
255
- This file exists in your app and it's free for you to change based
256
- on your needs.
330
+ When `require APP_PATH` is executed, `config/application.rb` is loaded (recall
331
+ that `APP_PATH` is defined in `bin/rails`). This file exists in your application
332
+ and it's free for you to change based on your needs.
257
333
 
258
334
  ### `Rails::Server#start`
259
335
 
260
- After `config/application` is loaded, `server.start` is called. This method is defined like this:
336
+ After `config/application` is loaded, `server.start` is called. This method is
337
+ defined like this:
261
338
 
262
339
  ```ruby
263
340
  def start
264
- url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
265
- puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
266
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
267
- puts "=> Run `rails server -h` for more startup options"
341
+ print_boot_information
268
342
  trap(:INT) { exit }
269
- puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
343
+ create_tmp_directories
344
+ log_to_stdout if options[:log_stdout]
345
+
346
+ super
347
+ ...
348
+ end
349
+
350
+ private
270
351
 
271
- #Create required tmp directories if not found
272
- %w(cache pids sessions sockets).each do |dir_to_make|
273
- FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
352
+ def print_boot_information
353
+ ...
354
+ puts "=> Run `rails server -h` for more startup options"
355
+ ...
356
+ puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
357
+ end
358
+
359
+ def create_tmp_directories
360
+ %w(cache pids sessions sockets).each do |dir_to_make|
361
+ FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make))
362
+ end
274
363
  end
275
364
 
276
- unless options[:daemonize]
365
+ def log_to_stdout
277
366
  wrapped_app # touch the app so the logger is set up
278
367
 
279
368
  console = ActiveSupport::Logger.new($stdout)
280
369
  console.formatter = Rails.logger.formatter
370
+ console.level = Rails.logger.level
281
371
 
282
372
  Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
283
373
  end
284
-
285
- super
286
- ensure
287
- # The '-h' option calls exit before @options is set.
288
- # If we call 'options' with it unset, we get double help banners.
289
- puts 'Exiting' unless @options && options[:daemonize]
290
- end
291
374
  ```
292
375
 
293
376
  This is where the first output of the Rails initialization happens. This
@@ -346,7 +429,7 @@ end
346
429
 
347
430
  The interesting part for a Rails app is the last line, `server.run`. Here we encounter the `wrapped_app` method again, which this time
348
431
  we're going to explore more (even though it was executed before, and
349
- thus memorized by now).
432
+ thus memoized by now).
350
433
 
351
434
  ```ruby
352
435
  @wrapped_app ||= build_app app
@@ -356,7 +439,11 @@ The `app` method here is defined like so:
356
439
 
357
440
  ```ruby
358
441
  def app
359
- @app ||= begin
442
+ @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
443
+ end
444
+ ...
445
+ private
446
+ def build_app_and_options_from_config
360
447
  if !::File.exist? options[:config]
361
448
  abort "configuration #{options[:config]} not found"
362
449
  end
@@ -365,7 +452,10 @@ def app
365
452
  self.options.merge! options
366
453
  app
367
454
  end
368
- end
455
+
456
+ def build_app_from_string
457
+ Rack::Builder.new_from_string(self.options[:builder])
458
+ end
369
459
  ```
370
460
 
371
461
  The `options[:config]` value defaults to `config.ru` which contains this:
@@ -373,7 +463,7 @@ The `options[:config]` value defaults to `config.ru` which contains this:
373
463
  ```ruby
374
464
  # This file is used by Rack-based servers to start the application.
375
465
 
376
- require ::File.expand_path('../config/environment', __FILE__)
466
+ require ::File.expand_path('../config/environment', __FILE__)
377
467
  run <%= app_const %>
378
468
  ```
379
469
 
@@ -381,25 +471,42 @@ run <%= app_const %>
381
471
  The `Rack::Builder.parse_file` method here takes the content from this `config.ru` file and parses it using this code:
382
472
 
383
473
  ```ruby
384
- app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
385
- TOPLEVEL_BINDING, config
474
+ app = new_from_string cfgfile, config
475
+
476
+ ...
477
+
478
+ def self.new_from_string(builder_script, file="(rackup)")
479
+ eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
480
+ TOPLEVEL_BINDING, file, 0
481
+ end
386
482
  ```
387
483
 
388
484
  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:
389
485
 
390
486
  ```ruby
391
- require ::File.expand_path('../config/environment', __FILE__)
487
+ require ::File.expand_path('../config/environment', __FILE__)
392
488
  ```
393
489
 
394
490
  ### `config/environment.rb`
395
491
 
396
492
  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.
397
493
 
398
- This file begins with requiring `config/application.rb`.
494
+ This file begins with requiring `config/application.rb`:
495
+
496
+ ```ruby
497
+ require File.expand_path('../application', __FILE__)
498
+ ```
399
499
 
400
500
  ### `config/application.rb`
401
501
 
402
- This file requires `config/boot.rb`, 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.
502
+ This file requires `config/boot.rb`:
503
+
504
+ ```ruby
505
+ require File.expand_path('../boot', __FILE__)
506
+ ```
507
+
508
+ But only if it hasn't been required before, which would be the case in `rails server`
509
+ but **wouldn't** be the case with Passenger.
403
510
 
404
511
  Then the fun begins!
405
512
 
@@ -420,11 +527,12 @@ This file is responsible for requiring all the individual frameworks of Rails:
420
527
  require "rails"
421
528
 
422
529
  %w(
423
- active_record
424
- action_controller
425
- action_mailer
426
- rails/test_unit
427
- sprockets
530
+ active_record
531
+ action_controller
532
+ action_view
533
+ action_mailer
534
+ rails/test_unit
535
+ sprockets
428
536
  ).each do |framework|
429
537
  begin
430
538
  require "#{framework}/railtie"
@@ -443,11 +551,13 @@ I18n and Rails configuration are all being defined here.
443
551
 
444
552
  ### Back to `config/environment.rb`
445
553
 
446
- When `config/application.rb` has finished loading Rails, and defined
554
+ The rest of `config/application.rb` defines the configuration for the
555
+ `Rails::Application` which will be used once the application is fully
556
+ initialized. When `config/application.rb` has finished loading Rails and defined
447
557
  the application namespace, we go back to `config/environment.rb`,
448
558
  where the application is initialized. For example, if the application was called
449
- `Blog`, here we would find `Blog::Application.initialize!`, which is
450
- defined in `rails/application.rb`
559
+ `Blog`, here we would find `Rails.application.initialize!`, which is
560
+ defined in `rails/application.rb`.
451
561
 
452
562
  ### `railties/lib/rails/application.rb`
453
563
 
@@ -462,16 +572,33 @@ def initialize!(group=:default) #:nodoc:
462
572
  end
463
573
  ```
464
574
 
465
- As you can see, you can only initialize an app once. This is also where the initializers are run.
575
+ As you can see, you can only initialize an app once. The initializers are run through
576
+ the `run_initializers` method which is defined in `railties/lib/rails/initializable.rb`:
466
577
 
467
- TODO: review this
578
+ ```ruby
579
+ def run_initializers(group=:default, *args)
580
+ return if instance_variable_defined?(:@ran)
581
+ initializers.tsort_each do |initializer|
582
+ initializer.run(*args) if initializer.belongs_to?(group)
583
+ end
584
+ @ran = true
585
+ end
586
+ ```
468
587
 
469
- The initializers code itself is tricky. What Rails is doing here is it
470
- traverses all the class ancestors looking for an `initializers` method,
471
- sorting them and running them. For example, the `Engine` class will make
472
- all the engines available by providing the `initializers` method.
588
+ The `run_initializers` code itself is tricky. What Rails is doing here is
589
+ traversing all the class ancestors looking for those that respond to an
590
+ `initializers` method. It then sorts the ancestors by name, and runs them.
591
+ For example, the `Engine` class will make all the engines available by
592
+ providing an `initializers` method on them.
473
593
 
474
- After this is done we go back to `Rack::Server`
594
+ The `Rails::Application` class, as defined in `railties/lib/rails/application.rb`
595
+ defines `bootstrap`, `railtie`, and `finisher` initializers. The `bootstrap` initializers
596
+ prepare the application (like initializing the logger) while the `finisher`
597
+ initializers (like building the middleware stack) are run last. The `railtie`
598
+ initializers are the initializers which have been defined on the `Rails::Application`
599
+ itself and are run between the `bootstrap` and `finishers`.
600
+
601
+ After this is done we go back to `Rack::Server`.
475
602
 
476
603
  ### Rack: lib/rack/server.rb
477
604
 
@@ -479,7 +606,11 @@ Last time we left when the `app` method was being defined:
479
606
 
480
607
  ```ruby
481
608
  def app
482
- @app ||= begin
609
+ @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
610
+ end
611
+ ...
612
+ private
613
+ def build_app_and_options_from_config
483
614
  if !::File.exist? options[:config]
484
615
  abort "configuration #{options[:config]} not found"
485
616
  end
@@ -488,7 +619,10 @@ def app
488
619
  self.options.merge! options
489
620
  app
490
621
  end
491
- end
622
+
623
+ def build_app_from_string
624
+ Rack::Builder.new_from_string(self.options[:builder])
625
+ end
492
626
  ```
493
627
 
494
628
  At this point `app` is the Rails app itself (a middleware), and what
@@ -506,7 +640,7 @@ def build_app(app)
506
640
  end
507
641
  ```
508
642
 
509
- Remember, `build_app` was called (by wrapped_app) in the last line of `Server#start`.
643
+ Remember, `build_app` was called (by `wrapped_app`) in the last line of `Server#start`.
510
644
  Here's how it looked like when we left:
511
645
 
512
646
  ```ruby
@@ -514,40 +648,50 @@ server.run wrapped_app, options, &blk
514
648
  ```
515
649
 
516
650
  At this point, the implementation of `server.run` will depend on the
517
- server you're using. For example, if you were using Mongrel, here's what
651
+ server you're using. For example, if you were using Puma, here's what
518
652
  the `run` method would look like:
519
653
 
520
654
  ```ruby
521
- def self.run(app, options={})
522
- server = ::Mongrel::HttpServer.new(
523
- options[:Host] || '0.0.0.0',
524
- options[:Port] || 8080,
525
- options[:num_processors] || 950,
526
- options[:throttle] || 0,
527
- options[:timeout] || 60)
528
- # Acts like Rack::URLMap, utilizing Mongrel's own path finding methods.
529
- # Use is similar to #run, replacing the app argument with a hash of
530
- # { path=>app, ... } or an instance of Rack::URLMap.
531
- if options[:map]
532
- if app.is_a? Hash
533
- app.each do |path, appl|
534
- path = '/'+path unless path[0] == ?/
535
- server.register(path, Rack::Handler::Mongrel.new(appl))
536
- end
537
- elsif app.is_a? URLMap
538
- app.instance_variable_get(:@mapping).each do |(host, path, appl)|
539
- next if !host.nil? && !options[:Host].nil? && options[:Host] != host
540
- path = '/'+path unless path[0] == ?/
541
- server.register(path, Rack::Handler::Mongrel.new(appl))
542
- end
543
- else
544
- raise ArgumentError, "first argument should be a Hash or URLMap"
545
- end
546
- else
547
- server.register('/', Rack::Handler::Mongrel.new(app))
655
+ ...
656
+ DEFAULT_OPTIONS = {
657
+ :Host => '0.0.0.0',
658
+ :Port => 8080,
659
+ :Threads => '0:16',
660
+ :Verbose => false
661
+ }
662
+
663
+ def self.run(app, options = {})
664
+ options = DEFAULT_OPTIONS.merge(options)
665
+
666
+ if options[:Verbose]
667
+ app = Rack::CommonLogger.new(app, STDOUT)
668
+ end
669
+
670
+ if options[:environment]
671
+ ENV['RACK_ENV'] = options[:environment].to_s
672
+ end
673
+
674
+ server = ::Puma::Server.new(app)
675
+ min, max = options[:Threads].split(':', 2)
676
+
677
+ puts "Puma #{::Puma::Const::PUMA_VERSION} starting..."
678
+ puts "* Min threads: #{min}, max threads: #{max}"
679
+ puts "* Environment: #{ENV['RACK_ENV']}"
680
+ puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
681
+
682
+ server.add_tcp_listener options[:Host], options[:Port]
683
+ server.min_threads = min
684
+ server.max_threads = max
685
+ yield server if block_given?
686
+
687
+ begin
688
+ server.run.join
689
+ rescue Interrupt
690
+ puts "* Gracefully stopping, waiting for requests to finish"
691
+ server.stop(true)
692
+ puts "* Goodbye!"
548
693
  end
549
- yield server if block_given?
550
- server.run.join
694
+
551
695
  end
552
696
  ```
553
697