rails 3.2.22.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +85 -0
  3. data/guides/CHANGELOG.md +31 -0
  4. data/guides/Rakefile +79 -0
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/belongs_to.png +0 -0
  7. data/guides/assets/images/book_icon.gif +0 -0
  8. data/guides/assets/images/bullet.gif +0 -0
  9. data/guides/assets/images/chapters_icon.gif +0 -0
  10. data/guides/assets/images/check_bullet.gif +0 -0
  11. data/guides/assets/images/credits_pic_blank.gif +0 -0
  12. data/guides/assets/images/csrf.png +0 -0
  13. data/guides/assets/images/edge_badge.png +0 -0
  14. data/guides/assets/images/favicon.ico +0 -0
  15. data/guides/assets/images/feature_tile.gif +0 -0
  16. data/guides/assets/images/footer_tile.gif +0 -0
  17. data/guides/assets/images/fxn.png +0 -0
  18. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  19. data/guides/assets/images/getting_started/challenge.png +0 -0
  20. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  21. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  22. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  23. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  24. data/guides/assets/images/getting_started/new_article.png +0 -0
  25. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  26. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  27. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  28. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  29. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  30. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  31. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  32. data/guides/assets/images/grey_bullet.gif +0 -0
  33. data/guides/assets/images/habtm.png +0 -0
  34. data/guides/assets/images/has_many.png +0 -0
  35. data/guides/assets/images/has_many_through.png +0 -0
  36. data/guides/assets/images/has_one.png +0 -0
  37. data/guides/assets/images/has_one_through.png +0 -0
  38. data/guides/assets/images/header_backdrop.png +0 -0
  39. data/guides/assets/images/header_tile.gif +0 -0
  40. data/guides/assets/images/i18n/demo_html_safe.png +0 -0
  41. data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
  42. data/guides/assets/images/i18n/demo_translated_en.png +0 -0
  43. data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
  44. data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
  45. data/guides/assets/images/i18n/demo_untranslated.png +0 -0
  46. data/guides/assets/images/icons/README +5 -0
  47. data/guides/assets/images/icons/callouts/1.png +0 -0
  48. data/guides/assets/images/icons/callouts/10.png +0 -0
  49. data/guides/assets/images/icons/callouts/11.png +0 -0
  50. data/guides/assets/images/icons/callouts/12.png +0 -0
  51. data/guides/assets/images/icons/callouts/13.png +0 -0
  52. data/guides/assets/images/icons/callouts/14.png +0 -0
  53. data/guides/assets/images/icons/callouts/15.png +0 -0
  54. data/guides/assets/images/icons/callouts/2.png +0 -0
  55. data/guides/assets/images/icons/callouts/3.png +0 -0
  56. data/guides/assets/images/icons/callouts/4.png +0 -0
  57. data/guides/assets/images/icons/callouts/5.png +0 -0
  58. data/guides/assets/images/icons/callouts/6.png +0 -0
  59. data/guides/assets/images/icons/callouts/7.png +0 -0
  60. data/guides/assets/images/icons/callouts/8.png +0 -0
  61. data/guides/assets/images/icons/callouts/9.png +0 -0
  62. data/guides/assets/images/icons/caution.png +0 -0
  63. data/guides/assets/images/icons/example.png +0 -0
  64. data/guides/assets/images/icons/home.png +0 -0
  65. data/guides/assets/images/icons/important.png +0 -0
  66. data/guides/assets/images/icons/next.png +0 -0
  67. data/guides/assets/images/icons/note.png +0 -0
  68. data/guides/assets/images/icons/prev.png +0 -0
  69. data/guides/assets/images/icons/tip.png +0 -0
  70. data/guides/assets/images/icons/up.png +0 -0
  71. data/guides/assets/images/icons/warning.png +0 -0
  72. data/guides/assets/images/nav_arrow.gif +0 -0
  73. data/guides/assets/images/oscardelben.jpg +0 -0
  74. data/guides/assets/images/polymorphic.png +0 -0
  75. data/guides/assets/images/radar.png +0 -0
  76. data/guides/assets/images/rails4_features.png +0 -0
  77. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  78. data/guides/assets/images/rails_guides_logo.gif +0 -0
  79. data/guides/assets/images/rails_logo_remix.gif +0 -0
  80. data/guides/assets/images/session_fixation.png +0 -0
  81. data/guides/assets/images/tab_grey.gif +0 -0
  82. data/guides/assets/images/tab_info.gif +0 -0
  83. data/guides/assets/images/tab_note.gif +0 -0
  84. data/guides/assets/images/tab_red.gif +0 -0
  85. data/guides/assets/images/tab_yellow.gif +0 -0
  86. data/guides/assets/images/tab_yellow.png +0 -0
  87. data/guides/assets/images/vijaydev.jpg +0 -0
  88. data/guides/assets/javascripts/guides.js +59 -0
  89. data/guides/assets/javascripts/jquery.min.js +4 -0
  90. data/guides/assets/javascripts/responsive-tables.js +43 -0
  91. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  92. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  93. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  94. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  95. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  96. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  97. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  98. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  99. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  100. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  101. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  102. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  103. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  104. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  105. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  106. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  107. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  108. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  109. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  110. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  111. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  112. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  113. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  114. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  115. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  116. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  117. data/guides/assets/stylesheets/fixes.css +16 -0
  118. data/guides/assets/stylesheets/kindle.css +11 -0
  119. data/guides/assets/stylesheets/main.css +713 -0
  120. data/guides/assets/stylesheets/print.css +52 -0
  121. data/guides/assets/stylesheets/reset.css +43 -0
  122. data/guides/assets/stylesheets/responsive-tables.css +50 -0
  123. data/guides/assets/stylesheets/style.css +13 -0
  124. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  125. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  126. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  127. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  128. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  129. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  130. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  131. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  132. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  133. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  134. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  135. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  136. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  137. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  138. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  139. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  140. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  141. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  142. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  143. data/guides/bug_report_templates/action_controller_master.rb +54 -0
  144. data/guides/bug_report_templates/active_record_gem.rb +40 -0
  145. data/guides/bug_report_templates/active_record_master.rb +49 -0
  146. data/guides/rails_guides/generator.rb +248 -0
  147. data/guides/rails_guides/helpers.rb +53 -0
  148. data/guides/rails_guides/indexer.rb +68 -0
  149. data/guides/rails_guides/kindle.rb +119 -0
  150. data/guides/rails_guides/levenshtein.rb +39 -0
  151. data/guides/rails_guides/markdown/renderer.rb +82 -0
  152. data/guides/rails_guides/markdown.rb +167 -0
  153. data/guides/rails_guides.rb +63 -0
  154. data/guides/source/2_2_release_notes.md +435 -0
  155. data/guides/source/2_3_release_notes.md +621 -0
  156. data/guides/source/3_0_release_notes.md +611 -0
  157. data/guides/source/3_1_release_notes.md +559 -0
  158. data/guides/source/3_2_release_notes.md +568 -0
  159. data/guides/source/4_0_release_notes.md +279 -0
  160. data/guides/source/4_1_release_notes.md +730 -0
  161. data/guides/source/4_2_release_notes.md +850 -0
  162. data/guides/source/_license.html.erb +2 -0
  163. data/guides/source/_welcome.html.erb +19 -0
  164. data/guides/source/action_controller_overview.md +1249 -0
  165. data/guides/source/action_mailer_basics.md +752 -0
  166. data/guides/source/action_view_overview.md +1620 -0
  167. data/guides/source/active_job_basics.md +318 -0
  168. data/guides/source/active_model_basics.md +554 -0
  169. data/guides/source/active_record_basics.md +374 -0
  170. data/guides/source/active_record_callbacks.md +413 -0
  171. data/guides/source/active_record_migrations.md +1018 -0
  172. data/guides/source/active_record_postgresql.md +433 -0
  173. data/guides/source/active_record_querying.md +1783 -0
  174. data/guides/source/active_record_validations.md +1178 -0
  175. data/guides/source/active_support_core_extensions.md +3904 -0
  176. data/guides/source/active_support_instrumentation.md +499 -0
  177. data/guides/source/api_documentation_guidelines.md +361 -0
  178. data/guides/source/asset_pipeline.md +1360 -0
  179. data/guides/source/association_basics.md +2236 -0
  180. data/guides/source/caching_with_rails.md +379 -0
  181. data/guides/source/command_line.md +625 -0
  182. data/guides/source/configuring.md +1045 -0
  183. data/guides/source/constant_autoloading_and_reloading.md +1297 -0
  184. data/guides/source/contributing_to_ruby_on_rails.md +624 -0
  185. data/guides/source/credits.html.erb +80 -0
  186. data/guides/source/debugging_rails_applications.md +861 -0
  187. data/guides/source/development_dependencies_install.md +289 -0
  188. data/guides/source/documents.yaml +205 -0
  189. data/guides/source/engines.md +1412 -0
  190. data/guides/source/form_helpers.md +1024 -0
  191. data/guides/source/generators.md +676 -0
  192. data/guides/source/getting_started.md +2085 -0
  193. data/guides/source/i18n.md +1086 -0
  194. data/guides/source/index.html.erb +28 -0
  195. data/guides/source/initialization.md +704 -0
  196. data/guides/source/kindle/copyright.html.erb +1 -0
  197. data/guides/source/kindle/layout.html.erb +27 -0
  198. data/guides/source/kindle/rails_guides.opf.erb +52 -0
  199. data/guides/source/kindle/toc.html.erb +24 -0
  200. data/guides/source/kindle/toc.ncx.erb +64 -0
  201. data/guides/source/kindle/welcome.html.erb +5 -0
  202. data/guides/source/layout.html.erb +143 -0
  203. data/guides/source/layouts_and_rendering.md +1227 -0
  204. data/guides/source/maintenance_policy.md +78 -0
  205. data/guides/source/nested_model_forms.md +228 -0
  206. data/guides/source/plugins.md +444 -0
  207. data/guides/source/rails_application_templates.md +266 -0
  208. data/guides/source/rails_on_rack.md +336 -0
  209. data/guides/source/routing.md +1141 -0
  210. data/guides/source/ruby_on_rails_guides_guidelines.md +127 -0
  211. data/guides/source/security.md +1024 -0
  212. data/guides/source/testing.md +1123 -0
  213. data/guides/source/upgrading_ruby_on_rails.md +1154 -0
  214. data/guides/source/working_with_javascript_in_rails.md +407 -0
  215. data/guides/w3c_validator.rb +97 -0
  216. metadata +290 -44
@@ -0,0 +1,704 @@
1
+ The Rails Initialization Process
2
+ ================================
3
+
4
+ This guide explains the internals of the initialization process in Rails
5
+ as of Rails 4. It is an extremely in-depth guide and recommended for advanced Rails developers.
6
+
7
+ After reading this guide, you will know:
8
+
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.
13
+
14
+ --------------------------------------------------------------------------------
15
+
16
+ This guide goes through every method call that is
17
+ required to boot up the Ruby on Rails stack for a default Rails 4
18
+ application, explaining each part in detail along the way. For this
19
+ guide, we will be focusing on what happens when you execute `rails server`
20
+ to boot your app.
21
+
22
+ NOTE: Paths in this guide are relative to Rails or a Rails application unless otherwise specified.
23
+
24
+ TIP: If you want to follow along while browsing the Rails [source
25
+ code](https://github.com/rails/rails), we recommend that you use the `t`
26
+ key binding to open the file finder inside GitHub and find files
27
+ quickly.
28
+
29
+ Launch!
30
+ -------
31
+
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
+ ```
68
+
69
+ ### `bin/rails`
70
+
71
+ This file is as follows:
72
+
73
+ ```ruby
74
+ #!/usr/bin/env ruby
75
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
76
+ require_relative '../config/boot'
77
+ require 'rails/commands'
78
+ ```
79
+
80
+ 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.
81
+
82
+ ### `config/boot.rb`
83
+
84
+ `config/boot.rb` contains:
85
+
86
+ ```ruby
87
+ # Set up gems listed in the Gemfile.
88
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
89
+
90
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
91
+ ```
92
+
93
+ In a standard Rails application, there's a `Gemfile` which declares all
94
+ dependencies of the application. `config/boot.rb` sets
95
+ `ENV['BUNDLE_GEMFILE']` to the location of this file. If the Gemfile
96
+ exists, then `bundler/setup` is required. The require is used by Bundler to
97
+ configure the load path for your Gemfile's dependencies.
98
+
99
+ A standard Rails application depends on several gems, specifically:
100
+
101
+ * actionmailer
102
+ * actionpack
103
+ * actionview
104
+ * activemodel
105
+ * activerecord
106
+ * activesupport
107
+ * arel
108
+ * builder
109
+ * bundler
110
+ * erubis
111
+ * i18n
112
+ * mail
113
+ * mime-types
114
+ * rack
115
+ * rack-cache
116
+ * rack-mount
117
+ * rack-test
118
+ * rails
119
+ * railties
120
+ * rake
121
+ * sqlite3
122
+ * thor
123
+ * tzinfo
124
+
125
+ ### `rails/commands.rb`
126
+
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:
130
+
131
+ ```ruby
132
+ ARGV << '--help' if ARGV.empty?
133
+
134
+ aliases = {
135
+ "g" => "generate",
136
+ "d" => "destroy",
137
+ "c" => "console",
138
+ "s" => "server",
139
+ "db" => "dbconsole",
140
+ "r" => "runner"
141
+ }
142
+
143
+ command = ARGV.shift
144
+ command = aliases[command] || command
145
+
146
+ require 'rails/commands/commands_tasks'
147
+
148
+ Rails::CommandsTasks.new(ARGV).run_command!(command)
149
+ ```
150
+
151
+ TIP: As you can see, an empty ARGV list will make Rails show the help
152
+ snippet.
153
+
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.
162
+
163
+ ```ruby
164
+ COMMAND_WHITELIST = %(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")
186
+
187
+ Rails::Server.new.tap do |server|
188
+ # We need to require application after the server sets environment,
189
+ # otherwise the --environment option given to the server won't propagate.
190
+ require APP_PATH
191
+ Dir.chdir(Rails.application.root)
192
+ server.start
193
+ end
194
+ end
195
+
196
+ def require_command!(command)
197
+ require "rails/commands/#{command}"
198
+ end
199
+ ```
200
+
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.
205
+
206
+ ```ruby
207
+ require 'fileutils'
208
+ require 'optparse'
209
+ require 'action_dispatch'
210
+ require 'rails'
211
+
212
+ module Rails
213
+ class Server < ::Rack::Server
214
+ ```
215
+
216
+ `fileutils` and `optparse` are standard Ruby libraries which provide helper functions for working with files and parsing options.
217
+
218
+ ### `actionpack/lib/action_dispatch.rb`
219
+
220
+ Action Dispatch is the routing component of the Rails framework.
221
+ It adds functionality like routing, session, and common middlewares.
222
+
223
+ ### `rails/commands/server.rb`
224
+
225
+ 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`:
226
+
227
+ ```ruby
228
+ def initialize(*)
229
+ super
230
+ set_environment
231
+ end
232
+ ```
233
+
234
+ Firstly, `super` is called which calls the `initialize` method on `Rack::Server`.
235
+
236
+ ### Rack: `lib/rack/server.rb`
237
+
238
+ `Rack::Server` is responsible for providing a common server interface for all Rack-based applications, which Rails is now a part of.
239
+
240
+ The `initialize` method in `Rack::Server` simply sets a couple of variables:
241
+
242
+ ```ruby
243
+ def initialize(options = nil)
244
+ @options = options
245
+ @app = options[:app] if options && options[:app]
246
+ end
247
+ ```
248
+
249
+ In this case, `options` will be `nil` so nothing happens in this method.
250
+
251
+ 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:
252
+
253
+ ```ruby
254
+ def set_environment
255
+ ENV["RAILS_ENV"] ||= options[:environment]
256
+ end
257
+ ```
258
+
259
+ In fact, the `options` method here does quite a lot. This method is defined in `Rack::Server` like this:
260
+
261
+ ```ruby
262
+ def options
263
+ @options ||= parse_options(ARGV)
264
+ end
265
+ ```
266
+
267
+ Then `parse_options` is defined like this:
268
+
269
+ ```ruby
270
+ def parse_options(args)
271
+ options = default_options
272
+
273
+ # Don't evaluate CGI ISINDEX parameters.
274
+ # http://www.meb.uni-bonn.de/docs/cgi/cl.html
275
+ args.clear if ENV.include?("REQUEST_METHOD")
276
+
277
+ options.merge! opt_parser.parse!(args)
278
+ options[:config] = ::File.expand_path(options[:config])
279
+ ENV["RACK_ENV"] = options[:environment]
280
+ options
281
+ end
282
+ ```
283
+
284
+ With the `default_options` set to this:
285
+
286
+ ```ruby
287
+ def default_options
288
+ environment = ENV['RACK_ENV'] || 'development'
289
+ default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
290
+
291
+ {
292
+ :environment => environment,
293
+ :pid => nil,
294
+ :Port => 9292,
295
+ :Host => default_host,
296
+ :AccessLog => [],
297
+ :config => "config.ru"
298
+ }
299
+ end
300
+ ```
301
+
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`:
303
+
304
+ ```ruby
305
+ def opt_parser
306
+ Options.new
307
+ end
308
+ ```
309
+
310
+ The class **is** defined in `Rack::Server`, but is overwritten in `Rails::Server` to take different arguments. Its `parse!` method begins like this:
311
+
312
+ ```ruby
313
+ def parse!(args)
314
+ args, options = args.dup, {}
315
+
316
+ opt_parser = OptionParser.new do |opts|
317
+ opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
318
+ opts.on("-p", "--port=port", Integer,
319
+ "Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
320
+ ...
321
+ ```
322
+
323
+ This method will set up keys for the `options` which Rails will then be
324
+ able to use to determine how its server should run. After `initialize`
325
+ has finished, we jump back into `rails/server` where `APP_PATH` (which was
326
+ set earlier) is required.
327
+
328
+ ### `config/application`
329
+
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.
333
+
334
+ ### `Rails::Server#start`
335
+
336
+ After `config/application` is loaded, `server.start` is called. This method is
337
+ defined like this:
338
+
339
+ ```ruby
340
+ def start
341
+ print_boot_information
342
+ trap(:INT) { exit }
343
+ create_tmp_directories
344
+ log_to_stdout if options[:log_stdout]
345
+
346
+ super
347
+ ...
348
+ end
349
+
350
+ private
351
+
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
363
+ end
364
+
365
+ def log_to_stdout
366
+ wrapped_app # touch the app so the logger is set up
367
+
368
+ console = ActiveSupport::Logger.new($stdout)
369
+ console.formatter = Rails.logger.formatter
370
+ console.level = Rails.logger.level
371
+
372
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
373
+ end
374
+ ```
375
+
376
+ This is where the first output of the Rails initialization happens. This
377
+ method creates a trap for `INT` signals, so if you `CTRL-C` the server,
378
+ it will exit the process. As we can see from the code here, it will
379
+ create the `tmp/cache`, `tmp/pids`, `tmp/sessions` and `tmp/sockets`
380
+ directories. It then calls `wrapped_app` which is responsible for
381
+ creating the Rack app, before creating and assigning an
382
+ instance of `ActiveSupport::Logger`.
383
+
384
+ The `super` method will call `Rack::Server.start` which begins its definition like this:
385
+
386
+ ```ruby
387
+ def start &blk
388
+ if options[:warn]
389
+ $-w = true
390
+ end
391
+
392
+ if includes = options[:include]
393
+ $LOAD_PATH.unshift(*includes)
394
+ end
395
+
396
+ if library = options[:require]
397
+ require library
398
+ end
399
+
400
+ if options[:debug]
401
+ $DEBUG = true
402
+ require 'pp'
403
+ p options[:server]
404
+ pp wrapped_app
405
+ pp app
406
+ end
407
+
408
+ check_pid! if options[:pid]
409
+
410
+ # Touch the wrapped app, so that the config.ru is loaded before
411
+ # daemonization (i.e. before chdir, etc).
412
+ wrapped_app
413
+
414
+ daemonize_app if options[:daemonize]
415
+
416
+ write_pid if options[:pid]
417
+
418
+ trap(:INT) do
419
+ if server.respond_to?(:shutdown)
420
+ server.shutdown
421
+ else
422
+ exit
423
+ end
424
+ end
425
+
426
+ server.run wrapped_app, options, &blk
427
+ end
428
+ ```
429
+
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
431
+ we're going to explore more (even though it was executed before, and
432
+ thus memoized by now).
433
+
434
+ ```ruby
435
+ @wrapped_app ||= build_app app
436
+ ```
437
+
438
+ The `app` method here is defined like so:
439
+
440
+ ```ruby
441
+ def app
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
447
+ if !::File.exist? options[:config]
448
+ abort "configuration #{options[:config]} not found"
449
+ end
450
+
451
+ app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
452
+ self.options.merge! options
453
+ app
454
+ end
455
+
456
+ def build_app_from_string
457
+ Rack::Builder.new_from_string(self.options[:builder])
458
+ end
459
+ ```
460
+
461
+ The `options[:config]` value defaults to `config.ru` which contains this:
462
+
463
+ ```ruby
464
+ # This file is used by Rack-based servers to start the application.
465
+
466
+ require ::File.expand_path('../config/environment', __FILE__)
467
+ run <%= app_const %>
468
+ ```
469
+
470
+
471
+ The `Rack::Builder.parse_file` method here takes the content from this `config.ru` file and parses it using this code:
472
+
473
+ ```ruby
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
482
+ ```
483
+
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:
485
+
486
+ ```ruby
487
+ require ::File.expand_path('../config/environment', __FILE__)
488
+ ```
489
+
490
+ ### `config/environment.rb`
491
+
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.
493
+
494
+ This file begins with requiring `config/application.rb`:
495
+
496
+ ```ruby
497
+ require File.expand_path('../application', __FILE__)
498
+ ```
499
+
500
+ ### `config/application.rb`
501
+
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.
510
+
511
+ Then the fun begins!
512
+
513
+ Loading Rails
514
+ -------------
515
+
516
+ The next line in `config/application.rb` is:
517
+
518
+ ```ruby
519
+ require 'rails/all'
520
+ ```
521
+
522
+ ### `railties/lib/rails/all.rb`
523
+
524
+ This file is responsible for requiring all the individual frameworks of Rails:
525
+
526
+ ```ruby
527
+ require "rails"
528
+
529
+ %w(
530
+ active_record
531
+ action_controller
532
+ action_view
533
+ action_mailer
534
+ rails/test_unit
535
+ sprockets
536
+ ).each do |framework|
537
+ begin
538
+ require "#{framework}/railtie"
539
+ rescue LoadError
540
+ end
541
+ end
542
+ ```
543
+
544
+ This is where all the Rails frameworks are loaded and thus made
545
+ available to the application. We won't go into detail of what happens
546
+ inside each of those frameworks, but you're encouraged to try and
547
+ explore them on your own.
548
+
549
+ For now, just keep in mind that common functionality like Rails engines,
550
+ I18n and Rails configuration are all being defined here.
551
+
552
+ ### Back to `config/environment.rb`
553
+
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
557
+ the application namespace, we go back to `config/environment.rb`,
558
+ where the application is initialized. For example, if the application was called
559
+ `Blog`, here we would find `Rails.application.initialize!`, which is
560
+ defined in `rails/application.rb`.
561
+
562
+ ### `railties/lib/rails/application.rb`
563
+
564
+ The `initialize!` method looks like this:
565
+
566
+ ```ruby
567
+ def initialize!(group=:default) #:nodoc:
568
+ raise "Application has been already initialized." if @initialized
569
+ run_initializers(group, self)
570
+ @initialized = true
571
+ self
572
+ end
573
+ ```
574
+
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`:
577
+
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
+ ```
587
+
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.
593
+
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`.
602
+
603
+ ### Rack: lib/rack/server.rb
604
+
605
+ Last time we left when the `app` method was being defined:
606
+
607
+ ```ruby
608
+ def app
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
614
+ if !::File.exist? options[:config]
615
+ abort "configuration #{options[:config]} not found"
616
+ end
617
+
618
+ app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
619
+ self.options.merge! options
620
+ app
621
+ end
622
+
623
+ def build_app_from_string
624
+ Rack::Builder.new_from_string(self.options[:builder])
625
+ end
626
+ ```
627
+
628
+ At this point `app` is the Rails app itself (a middleware), and what
629
+ happens next is Rack will call all the provided middlewares:
630
+
631
+ ```ruby
632
+ def build_app(app)
633
+ middleware[options[:environment]].reverse_each do |middleware|
634
+ middleware = middleware.call(self) if middleware.respond_to?(:call)
635
+ next unless middleware
636
+ klass = middleware.shift
637
+ app = klass.new(app, *middleware)
638
+ end
639
+ app
640
+ end
641
+ ```
642
+
643
+ Remember, `build_app` was called (by `wrapped_app`) in the last line of `Server#start`.
644
+ Here's how it looked like when we left:
645
+
646
+ ```ruby
647
+ server.run wrapped_app, options, &blk
648
+ ```
649
+
650
+ At this point, the implementation of `server.run` will depend on the
651
+ server you're using. For example, if you were using Puma, here's what
652
+ the `run` method would look like:
653
+
654
+ ```ruby
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!"
693
+ end
694
+
695
+ end
696
+ ```
697
+
698
+ We won't dig into the server configuration itself, but this is
699
+ the last piece of our journey in the Rails initialization process.
700
+
701
+ This high level overview will help you understand when your code is
702
+ executed and how, and overall become a better Rails developer. If you
703
+ still want to know more, the Rails source code itself is probably the
704
+ best place to go next.
@@ -0,0 +1 @@
1
+ <%= render 'license' %>