rails 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +11 -7
- metadata +38 -237
- data/guides/CHANGELOG.md +0 -113
- data/guides/Rakefile +0 -92
- data/guides/assets/images/akshaysurve.jpg +0 -0
- data/guides/assets/images/belongs_to.png +0 -0
- data/guides/assets/images/book_icon.gif +0 -0
- data/guides/assets/images/bullet.gif +0 -0
- data/guides/assets/images/chapters_icon.gif +0 -0
- data/guides/assets/images/check_bullet.gif +0 -0
- data/guides/assets/images/credits_pic_blank.gif +0 -0
- data/guides/assets/images/csrf.png +0 -0
- data/guides/assets/images/edge_badge.png +0 -0
- data/guides/assets/images/favicon.ico +0 -0
- data/guides/assets/images/feature_tile.gif +0 -0
- data/guides/assets/images/footer_tile.gif +0 -0
- data/guides/assets/images/fxn.png +0 -0
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/images/getting_started/challenge.png +0 -0
- data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
- data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
- data/guides/assets/images/getting_started/form_with_errors.png +0 -0
- data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
- data/guides/assets/images/getting_started/new_article.png +0 -0
- data/guides/assets/images/getting_started/rails_welcome.png +0 -0
- data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
- data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
- data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
- data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
- data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
- data/guides/assets/images/grey_bullet.gif +0 -0
- data/guides/assets/images/habtm.png +0 -0
- data/guides/assets/images/has_many.png +0 -0
- data/guides/assets/images/has_many_through.png +0 -0
- data/guides/assets/images/has_one.png +0 -0
- data/guides/assets/images/has_one_through.png +0 -0
- data/guides/assets/images/header_backdrop.png +0 -0
- data/guides/assets/images/header_tile.gif +0 -0
- data/guides/assets/images/i18n/demo_html_safe.png +0 -0
- data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
- data/guides/assets/images/i18n/demo_translated_en.png +0 -0
- data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
- data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
- data/guides/assets/images/i18n/demo_untranslated.png +0 -0
- data/guides/assets/images/icons/README +0 -5
- data/guides/assets/images/icons/callouts/1.png +0 -0
- data/guides/assets/images/icons/callouts/10.png +0 -0
- data/guides/assets/images/icons/callouts/11.png +0 -0
- data/guides/assets/images/icons/callouts/12.png +0 -0
- data/guides/assets/images/icons/callouts/13.png +0 -0
- data/guides/assets/images/icons/callouts/14.png +0 -0
- data/guides/assets/images/icons/callouts/15.png +0 -0
- data/guides/assets/images/icons/callouts/2.png +0 -0
- data/guides/assets/images/icons/callouts/3.png +0 -0
- data/guides/assets/images/icons/callouts/4.png +0 -0
- data/guides/assets/images/icons/callouts/5.png +0 -0
- data/guides/assets/images/icons/callouts/6.png +0 -0
- data/guides/assets/images/icons/callouts/7.png +0 -0
- data/guides/assets/images/icons/callouts/8.png +0 -0
- data/guides/assets/images/icons/callouts/9.png +0 -0
- data/guides/assets/images/icons/caution.png +0 -0
- data/guides/assets/images/icons/example.png +0 -0
- data/guides/assets/images/icons/home.png +0 -0
- data/guides/assets/images/icons/important.png +0 -0
- data/guides/assets/images/icons/next.png +0 -0
- data/guides/assets/images/icons/note.png +0 -0
- data/guides/assets/images/icons/prev.png +0 -0
- data/guides/assets/images/icons/tip.png +0 -0
- data/guides/assets/images/icons/up.png +0 -0
- data/guides/assets/images/icons/warning.png +0 -0
- data/guides/assets/images/nav_arrow.gif +0 -0
- data/guides/assets/images/oscardelben.jpg +0 -0
- data/guides/assets/images/polymorphic.png +0 -0
- data/guides/assets/images/radar.png +0 -0
- data/guides/assets/images/rails4_features.png +0 -0
- data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
- data/guides/assets/images/rails_guides_logo.gif +0 -0
- data/guides/assets/images/rails_logo_remix.gif +0 -0
- data/guides/assets/images/session_fixation.png +0 -0
- data/guides/assets/images/tab_grey.gif +0 -0
- data/guides/assets/images/tab_info.gif +0 -0
- data/guides/assets/images/tab_note.gif +0 -0
- data/guides/assets/images/tab_red.gif +0 -0
- data/guides/assets/images/tab_yellow.gif +0 -0
- data/guides/assets/images/tab_yellow.png +0 -0
- data/guides/assets/images/vijaydev.jpg +0 -0
- data/guides/assets/javascripts/guides.js +0 -59
- data/guides/assets/javascripts/jquery.min.js +0 -4
- data/guides/assets/javascripts/responsive-tables.js +0 -43
- data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +0 -59
- data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +0 -75
- data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +0 -59
- data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +0 -65
- data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +0 -100
- data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +0 -97
- data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +0 -91
- data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +0 -55
- data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +0 -41
- data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +0 -52
- data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +0 -67
- data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +0 -52
- data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +0 -57
- data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +0 -58
- data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +0 -72
- data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +0 -88
- data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +0 -33
- data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +0 -74
- data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +0 -64
- data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +0 -55
- data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +0 -94
- data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +0 -51
- data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +0 -66
- data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +0 -56
- data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +0 -69
- data/guides/assets/javascripts/syntaxhighlighter/shCore.js +0 -17
- data/guides/assets/stylesheets/fixes.css +0 -16
- data/guides/assets/stylesheets/kindle.css +0 -11
- data/guides/assets/stylesheets/main.css +0 -713
- data/guides/assets/stylesheets/print.css +0 -52
- data/guides/assets/stylesheets/reset.css +0 -43
- data/guides/assets/stylesheets/responsive-tables.css +0 -50
- data/guides/assets/stylesheets/style.css +0 -13
- data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +0 -226
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +0 -328
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +0 -331
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +0 -339
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +0 -324
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +0 -328
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +0 -324
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +0 -324
- data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +0 -324
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +0 -117
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +0 -120
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +0 -128
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +0 -113
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +0 -117
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +0 -113
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +0 -113
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +0 -113
- data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +0 -116
- data/guides/bug_report_templates/action_controller_gem.rb +0 -47
- data/guides/bug_report_templates/action_controller_master.rb +0 -54
- data/guides/bug_report_templates/active_record_gem.rb +0 -40
- data/guides/bug_report_templates/active_record_master.rb +0 -49
- data/guides/bug_report_templates/generic_gem.rb +0 -15
- data/guides/bug_report_templates/generic_master.rb +0 -26
- data/guides/rails_guides.rb +0 -63
- data/guides/rails_guides/generator.rb +0 -248
- data/guides/rails_guides/helpers.rb +0 -53
- data/guides/rails_guides/indexer.rb +0 -68
- data/guides/rails_guides/kindle.rb +0 -119
- data/guides/rails_guides/levenshtein.rb +0 -37
- data/guides/rails_guides/markdown.rb +0 -167
- data/guides/rails_guides/markdown/renderer.rb +0 -82
- data/guides/source/2_2_release_notes.md +0 -435
- data/guides/source/2_3_release_notes.md +0 -621
- data/guides/source/3_0_release_notes.md +0 -611
- data/guides/source/3_1_release_notes.md +0 -559
- data/guides/source/3_2_release_notes.md +0 -568
- data/guides/source/4_0_release_notes.md +0 -279
- data/guides/source/4_1_release_notes.md +0 -730
- data/guides/source/4_2_release_notes.md +0 -877
- data/guides/source/_license.html.erb +0 -2
- data/guides/source/_welcome.html.erb +0 -23
- data/guides/source/action_controller_overview.md +0 -1192
- data/guides/source/action_mailer_basics.md +0 -757
- data/guides/source/action_view_overview.md +0 -1561
- data/guides/source/active_job_basics.md +0 -339
- data/guides/source/active_model_basics.md +0 -554
- data/guides/source/active_record_basics.md +0 -374
- data/guides/source/active_record_callbacks.md +0 -413
- data/guides/source/active_record_migrations.md +0 -1018
- data/guides/source/active_record_postgresql.md +0 -433
- data/guides/source/active_record_querying.md +0 -1781
- data/guides/source/active_record_validations.md +0 -1179
- data/guides/source/active_support_core_extensions.md +0 -3856
- data/guides/source/active_support_instrumentation.md +0 -488
- data/guides/source/api_documentation_guidelines.md +0 -361
- data/guides/source/asset_pipeline.md +0 -1304
- data/guides/source/association_basics.md +0 -2245
- data/guides/source/autoloading_and_reloading_constants.md +0 -1311
- data/guides/source/caching_with_rails.md +0 -379
- data/guides/source/command_line.md +0 -625
- data/guides/source/configuring.md +0 -1070
- data/guides/source/contributing_to_ruby_on_rails.md +0 -628
- data/guides/source/credits.html.erb +0 -80
- data/guides/source/debugging_rails_applications.md +0 -861
- data/guides/source/development_dependencies_install.md +0 -289
- data/guides/source/documents.yaml +0 -205
- data/guides/source/engines.md +0 -1412
- data/guides/source/form_helpers.md +0 -1024
- data/guides/source/generators.md +0 -676
- data/guides/source/getting_started.md +0 -2086
- data/guides/source/i18n.md +0 -1087
- data/guides/source/index.html.erb +0 -28
- data/guides/source/initialization.md +0 -704
- data/guides/source/kindle/copyright.html.erb +0 -1
- data/guides/source/kindle/layout.html.erb +0 -27
- data/guides/source/kindle/rails_guides.opf.erb +0 -52
- data/guides/source/kindle/toc.html.erb +0 -24
- data/guides/source/kindle/toc.ncx.erb +0 -64
- data/guides/source/kindle/welcome.html.erb +0 -5
- data/guides/source/layout.html.erb +0 -140
- data/guides/source/layouts_and_rendering.md +0 -1226
- data/guides/source/maintenance_policy.md +0 -78
- data/guides/source/nested_model_forms.md +0 -228
- data/guides/source/plugins.md +0 -444
- data/guides/source/rails_application_templates.md +0 -266
- data/guides/source/rails_on_rack.md +0 -335
- data/guides/source/routing.md +0 -1155
- data/guides/source/ruby_on_rails_guides_guidelines.md +0 -127
- data/guides/source/security.md +0 -1024
- data/guides/source/testing.md +0 -1132
- data/guides/source/upgrading_ruby_on_rails.md +0 -1186
- data/guides/source/working_with_javascript_in_rails.md +0 -407
- data/guides/w3c_validator.rb +0 -97
@@ -1,1311 +0,0 @@
|
|
1
|
-
Autoloading and Reloading Constants
|
2
|
-
===================================
|
3
|
-
|
4
|
-
This guide documents how constant autoloading and reloading works.
|
5
|
-
|
6
|
-
After reading this guide, you will know:
|
7
|
-
|
8
|
-
* Key aspects of Ruby constants
|
9
|
-
* What is `autoload_paths`
|
10
|
-
* How constant autoloading works
|
11
|
-
* What is `require_dependency`
|
12
|
-
* How constant reloading works
|
13
|
-
* Solutions to common autoloading gotchas
|
14
|
-
|
15
|
-
--------------------------------------------------------------------------------
|
16
|
-
|
17
|
-
|
18
|
-
Introduction
|
19
|
-
------------
|
20
|
-
|
21
|
-
Ruby on Rails allows applications to be written as if their code was preloaded.
|
22
|
-
|
23
|
-
In a normal Ruby program classes need to load their dependencies:
|
24
|
-
|
25
|
-
```ruby
|
26
|
-
require 'application_controller'
|
27
|
-
require 'post'
|
28
|
-
|
29
|
-
class PostsController < ApplicationController
|
30
|
-
def index
|
31
|
-
@posts = Post.all
|
32
|
-
end
|
33
|
-
end
|
34
|
-
```
|
35
|
-
|
36
|
-
Our Rubyist instinct quickly sees some redundancy in there: If classes were
|
37
|
-
defined in files matching their name, couldn't their loading be automated
|
38
|
-
somehow? We could save scanning the file for dependencies, which is brittle.
|
39
|
-
|
40
|
-
Moreover, `Kernel#require` loads files once, but development is much more smooth
|
41
|
-
if code gets refreshed when it changes without restarting the server. It would
|
42
|
-
be nice to be able to use `Kernel#load` in development, and `Kernel#require` in
|
43
|
-
production.
|
44
|
-
|
45
|
-
Indeed, those features are provided by Ruby on Rails, where we just write
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
class PostsController < ApplicationController
|
49
|
-
def index
|
50
|
-
@posts = Post.all
|
51
|
-
end
|
52
|
-
end
|
53
|
-
```
|
54
|
-
|
55
|
-
This guide documents how that works.
|
56
|
-
|
57
|
-
|
58
|
-
Constants Refresher
|
59
|
-
-------------------
|
60
|
-
|
61
|
-
While constants are trivial in most programming languages, they are a rich
|
62
|
-
topic in Ruby.
|
63
|
-
|
64
|
-
It is beyond the scope of this guide to document Ruby constants, but we are
|
65
|
-
nevertheless going to highlight a few key topics. Truly grasping the following
|
66
|
-
sections is instrumental to understanding constant autoloading and reloading.
|
67
|
-
|
68
|
-
### Nesting
|
69
|
-
|
70
|
-
Class and module definitions can be nested to create namespaces:
|
71
|
-
|
72
|
-
```ruby
|
73
|
-
module XML
|
74
|
-
class SAXParser
|
75
|
-
# (1)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
```
|
79
|
-
|
80
|
-
The *nesting* at any given place is the collection of enclosing nested class and
|
81
|
-
module objects outwards. The nesting at any given place can be inspected with
|
82
|
-
`Module.nesting`. For example, in the previous example, the nesting at
|
83
|
-
(1) is
|
84
|
-
|
85
|
-
```ruby
|
86
|
-
[XML::SAXParser, XML]
|
87
|
-
```
|
88
|
-
|
89
|
-
It is important to understand that the nesting is composed of class and module
|
90
|
-
*objects*, it has nothing to do with the constants used to access them, and is
|
91
|
-
also unrelated to their names.
|
92
|
-
|
93
|
-
For instance, while this definition is similar to the previous one:
|
94
|
-
|
95
|
-
```ruby
|
96
|
-
class XML::SAXParser
|
97
|
-
# (2)
|
98
|
-
end
|
99
|
-
```
|
100
|
-
|
101
|
-
the nesting in (2) is different:
|
102
|
-
|
103
|
-
```ruby
|
104
|
-
[XML::SAXParser]
|
105
|
-
```
|
106
|
-
|
107
|
-
`XML` does not belong to it.
|
108
|
-
|
109
|
-
We can see in this example that the name of a class or module that belongs to a
|
110
|
-
certain nesting does not necessarily correlate with the namespaces at the spot.
|
111
|
-
|
112
|
-
Even more, they are totally independent, take for instance
|
113
|
-
|
114
|
-
```ruby
|
115
|
-
module X
|
116
|
-
module Y
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
module A
|
121
|
-
module B
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
module X::Y
|
126
|
-
module A::B
|
127
|
-
# (3)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
```
|
131
|
-
|
132
|
-
The nesting in (3) consists of two module objects:
|
133
|
-
|
134
|
-
```ruby
|
135
|
-
[A::B, X::Y]
|
136
|
-
```
|
137
|
-
|
138
|
-
So, it not only doesn't end in `A`, which does not even belong to the nesting,
|
139
|
-
but it also contains `X::Y`, which is independent from `A::B`.
|
140
|
-
|
141
|
-
The nesting is an internal stack maintained by the interpreter, and it gets
|
142
|
-
modified according to these rules:
|
143
|
-
|
144
|
-
* The class object following a `class` keyword gets pushed when its body is
|
145
|
-
executed, and popped after it.
|
146
|
-
|
147
|
-
* The module object following a `module` keyword gets pushed when its body is
|
148
|
-
executed, and popped after it.
|
149
|
-
|
150
|
-
* A singleton class opened with `class << object` gets pushed, and popped later.
|
151
|
-
|
152
|
-
* When `instance_eval` is called using a string argument,
|
153
|
-
the singleton class of the receiver is pushed to the nesting of the eval'ed
|
154
|
-
code. When `class_eval` or `module_eval` is called using a string argument,
|
155
|
-
the receiver is pushed to the nesting of the eval'ed code.
|
156
|
-
|
157
|
-
* The nesting at the top-level of code interpreted by `Kernel#load` is empty
|
158
|
-
unless the `load` call receives a true value as second argument, in which case
|
159
|
-
a newly created anonymous module is pushed by Ruby.
|
160
|
-
|
161
|
-
It is interesting to observe that blocks do not modify the stack. In particular
|
162
|
-
the blocks that may be passed to `Class.new` and `Module.new` do not get the
|
163
|
-
class or module being defined pushed to their nesting. That's one of the
|
164
|
-
differences between defining classes and modules in one way or another.
|
165
|
-
|
166
|
-
### Class and Module Definitions are Constant Assignments
|
167
|
-
|
168
|
-
Let's suppose the following snippet creates a class (rather than reopening it):
|
169
|
-
|
170
|
-
```ruby
|
171
|
-
class C
|
172
|
-
end
|
173
|
-
```
|
174
|
-
|
175
|
-
Ruby creates a constant `C` in `Object` and stores in that constant a class
|
176
|
-
object. The name of the class instance is "C", a string, named after the
|
177
|
-
constant.
|
178
|
-
|
179
|
-
That is,
|
180
|
-
|
181
|
-
```ruby
|
182
|
-
class Project < ActiveRecord::Base
|
183
|
-
end
|
184
|
-
```
|
185
|
-
|
186
|
-
performs a constant assignment equivalent to
|
187
|
-
|
188
|
-
```ruby
|
189
|
-
Project = Class.new(ActiveRecord::Base)
|
190
|
-
```
|
191
|
-
|
192
|
-
including setting the name of the class as a side-effect:
|
193
|
-
|
194
|
-
```ruby
|
195
|
-
Project.name # => "Project"
|
196
|
-
```
|
197
|
-
|
198
|
-
Constant assignment has a special rule to make that happen: if the object
|
199
|
-
being assigned is an anonymous class or module, Ruby sets the object's name to
|
200
|
-
the name of the constant.
|
201
|
-
|
202
|
-
INFO. From then on, what happens to the constant and the instance does not
|
203
|
-
matter. For example, the constant could be deleted, the class object could be
|
204
|
-
assigned to a different constant, be stored in no constant anymore, etc. Once
|
205
|
-
the name is set, it doesn't change.
|
206
|
-
|
207
|
-
Similarly, module creation using the `module` keyword as in
|
208
|
-
|
209
|
-
```ruby
|
210
|
-
module Admin
|
211
|
-
end
|
212
|
-
```
|
213
|
-
|
214
|
-
performs a constant assignment equivalent to
|
215
|
-
|
216
|
-
```ruby
|
217
|
-
Admin = Module.new
|
218
|
-
```
|
219
|
-
|
220
|
-
including setting the name as a side-effect:
|
221
|
-
|
222
|
-
```ruby
|
223
|
-
Admin.name # => "Admin"
|
224
|
-
```
|
225
|
-
|
226
|
-
WARNING. The execution context of a block passed to `Class.new` or `Module.new`
|
227
|
-
is not entirely equivalent to the one of the body of the definitions using the
|
228
|
-
`class` and `module` keywords. But both idioms result in the same constant
|
229
|
-
assignment.
|
230
|
-
|
231
|
-
Thus, when one informally says "the `String` class", that really means: the
|
232
|
-
class object stored in the constant called "String" in the class object stored
|
233
|
-
in the `Object` constant. `String` is otherwise an ordinary Ruby constant and
|
234
|
-
everything related to constants such as resolution algorithms applies to it.
|
235
|
-
|
236
|
-
Likewise, in the controller
|
237
|
-
|
238
|
-
```ruby
|
239
|
-
class PostsController < ApplicationController
|
240
|
-
def index
|
241
|
-
@posts = Post.all
|
242
|
-
end
|
243
|
-
end
|
244
|
-
```
|
245
|
-
|
246
|
-
`Post` is not syntax for a class. Rather, `Post` is a regular Ruby constant. If
|
247
|
-
all is good, the constant is evaluated to an object that responds to `all`.
|
248
|
-
|
249
|
-
That is why we talk about *constant* autoloading, Rails has the ability to
|
250
|
-
load constants on the fly.
|
251
|
-
|
252
|
-
### Constants are Stored in Modules
|
253
|
-
|
254
|
-
Constants belong to modules in a very literal sense. Classes and modules have
|
255
|
-
a constant table; think of it as a hash table.
|
256
|
-
|
257
|
-
Let's analyze an example to really understand what that means. While common
|
258
|
-
abuses of language like "the `String` class" are convenient, the exposition is
|
259
|
-
going to be precise here for didactic purposes.
|
260
|
-
|
261
|
-
Let's consider the following module definition:
|
262
|
-
|
263
|
-
```ruby
|
264
|
-
module Colors
|
265
|
-
RED = '0xff0000'
|
266
|
-
end
|
267
|
-
```
|
268
|
-
|
269
|
-
First, when the `module` keyword is processed, the interpreter creates a new
|
270
|
-
entry in the constant table of the class object stored in the `Object` constant.
|
271
|
-
Said entry associates the name "Colors" to a newly created module object.
|
272
|
-
Furthermore, the interpreter sets the name of the new module object to be the
|
273
|
-
string "Colors".
|
274
|
-
|
275
|
-
Later, when the body of the module definition is interpreted, a new entry is
|
276
|
-
created in the constant table of the module object stored in the `Colors`
|
277
|
-
constant. That entry maps the name "RED" to the string "0xff0000".
|
278
|
-
|
279
|
-
In particular, `Colors::RED` is totally unrelated to any other `RED` constant
|
280
|
-
that may live in any other class or module object. If there were any, they
|
281
|
-
would have separate entries in their respective constant tables.
|
282
|
-
|
283
|
-
Pay special attention in the previous paragraphs to the distinction between
|
284
|
-
class and module objects, constant names, and value objects associated to them
|
285
|
-
in constant tables.
|
286
|
-
|
287
|
-
### Resolution Algorithms
|
288
|
-
|
289
|
-
#### Resolution Algorithm for Relative Constants
|
290
|
-
|
291
|
-
At any given place in the code, let's define *cref* to be the first element of
|
292
|
-
the nesting if it is not empty, or `Object` otherwise.
|
293
|
-
|
294
|
-
Without getting too much into the details, the resolution algorithm for relative
|
295
|
-
constant references goes like this:
|
296
|
-
|
297
|
-
1. If the nesting is not empty the constant is looked up in its elements and in
|
298
|
-
order. The ancestors of those elements are ignored.
|
299
|
-
|
300
|
-
2. If not found, then the algorithm walks up the ancestor chain of the cref.
|
301
|
-
|
302
|
-
3. If not found and the cref is a module, the constant is looked up in `Object`.
|
303
|
-
|
304
|
-
4. If not found, `const_missing` is invoked on the cref. The default
|
305
|
-
implementation of `const_missing` raises `NameError`, but it can be overridden.
|
306
|
-
|
307
|
-
Rails autoloading **does not emulate this algorithm**, but its starting point is
|
308
|
-
the name of the constant to be autoloaded, and the cref. See more in [Relative
|
309
|
-
References](#autoloading-algorithms-relative-references).
|
310
|
-
|
311
|
-
#### Resolution Algorithm for Qualified Constants
|
312
|
-
|
313
|
-
Qualified constants look like this:
|
314
|
-
|
315
|
-
```ruby
|
316
|
-
Billing::Invoice
|
317
|
-
```
|
318
|
-
|
319
|
-
`Billing::Invoice` is composed of two constants: `Billing` is relative and is
|
320
|
-
resolved using the algorithm of the previous section.
|
321
|
-
|
322
|
-
INFO. Leading colons would make the first segment absolute rather than
|
323
|
-
relative: `::Billing::Invoice`. That would force `Billing` to be looked up
|
324
|
-
only as a top-level constant.
|
325
|
-
|
326
|
-
`Invoice` on the other hand is qualified by `Billing` and we are going to see
|
327
|
-
its resolution next. Let's define *parent* to be that qualifying class or module
|
328
|
-
object, that is, `Billing` in the example above. The algorithm for qualified
|
329
|
-
constants goes like this:
|
330
|
-
|
331
|
-
1. The constant is looked up in the parent and its ancestors.
|
332
|
-
|
333
|
-
2. If the lookup fails, `const_missing` is invoked in the parent. The default
|
334
|
-
implementation of `const_missing` raises `NameError`, but it can be overridden.
|
335
|
-
|
336
|
-
As you see, this algorithm is simpler than the one for relative constants. In
|
337
|
-
particular, the nesting plays no role here, and modules are not special-cased,
|
338
|
-
if neither they nor their ancestors have the constants, `Object` is **not**
|
339
|
-
checked.
|
340
|
-
|
341
|
-
Rails autoloading **does not emulate this algorithm**, but its starting point is
|
342
|
-
the name of the constant to be autoloaded, and the parent. See more in
|
343
|
-
[Qualified References](#autoloading-algorithms-qualified-references).
|
344
|
-
|
345
|
-
|
346
|
-
Vocabulary
|
347
|
-
----------
|
348
|
-
|
349
|
-
### Parent Namespaces
|
350
|
-
|
351
|
-
Given a string with a constant path we define its *parent namespace* to be the
|
352
|
-
string that results from removing its rightmost segment.
|
353
|
-
|
354
|
-
For example, the parent namespace of the string "A::B::C" is the string "A::B",
|
355
|
-
the parent namespace of "A::B" is "A", and the parent namespace of "A" is "".
|
356
|
-
|
357
|
-
The interpretation of a parent namespace when thinking about classes and modules
|
358
|
-
is tricky though. Let's consider a module M named "A::B":
|
359
|
-
|
360
|
-
* The parent namespace, "A", may not reflect nesting at a given spot.
|
361
|
-
|
362
|
-
* The constant `A` may no longer exist, some code could have removed it from
|
363
|
-
`Object`.
|
364
|
-
|
365
|
-
* If `A` exists, the class or module that was originally in `A` may not be there
|
366
|
-
anymore. For example, if after a constant removal there was another constant
|
367
|
-
assignment there would generally be a different object in there.
|
368
|
-
|
369
|
-
* In such case, it could even happen that the reassigned `A` held a new class or
|
370
|
-
module called also "A"!
|
371
|
-
|
372
|
-
* In the previous scenarios M would no longer be reachable through `A::B` but
|
373
|
-
the module object itself could still be alive somewhere and its name would
|
374
|
-
still be "A::B".
|
375
|
-
|
376
|
-
The idea of a parent namespace is at the core of the autoloading algorithms
|
377
|
-
and helps explain and understand their motivation intuitively, but as you see
|
378
|
-
that metaphor leaks easily. Given an edge case to reason about, take always into
|
379
|
-
account that by "parent namespace" the guide means exactly that specific string
|
380
|
-
derivation.
|
381
|
-
|
382
|
-
### Loading Mechanism
|
383
|
-
|
384
|
-
Rails autoloads files with `Kernel#load` when `config.cache_classes` is false,
|
385
|
-
the default in development mode, and with `Kernel#require` otherwise, the
|
386
|
-
default in production mode.
|
387
|
-
|
388
|
-
`Kernel#load` allows Rails to execute files more than once if [constant
|
389
|
-
reloading](#constant-reloading) is enabled.
|
390
|
-
|
391
|
-
This guide uses the word "load" freely to mean a given file is interpreted, but
|
392
|
-
the actual mechanism can be `Kernel#load` or `Kernel#require` depending on that
|
393
|
-
flag.
|
394
|
-
|
395
|
-
|
396
|
-
Autoloading Availability
|
397
|
-
------------------------
|
398
|
-
|
399
|
-
Rails is always able to autoload provided its environment is in place. For
|
400
|
-
example the `runner` command autoloads:
|
401
|
-
|
402
|
-
```
|
403
|
-
$ bin/rails runner 'p User.column_names'
|
404
|
-
["id", "email", "created_at", "updated_at"]
|
405
|
-
```
|
406
|
-
|
407
|
-
The console autoloads, the test suite autoloads, and of course the application
|
408
|
-
autoloads.
|
409
|
-
|
410
|
-
By default, Rails eager loads the application files when it boots in production
|
411
|
-
mode, so most of the autoloading going on in development does not happen. But
|
412
|
-
autoloading may still be triggered during eager loading.
|
413
|
-
|
414
|
-
For example, given
|
415
|
-
|
416
|
-
```ruby
|
417
|
-
class BeachHouse < House
|
418
|
-
end
|
419
|
-
```
|
420
|
-
|
421
|
-
if `House` is still unknown when `app/models/beach_house.rb` is being eager
|
422
|
-
loaded, Rails autoloads it.
|
423
|
-
|
424
|
-
|
425
|
-
autoload_paths
|
426
|
-
--------------
|
427
|
-
|
428
|
-
As you probably know, when `require` gets a relative file name:
|
429
|
-
|
430
|
-
```ruby
|
431
|
-
require 'erb'
|
432
|
-
```
|
433
|
-
|
434
|
-
Ruby looks for the file in the directories listed in `$LOAD_PATH`. That is, Ruby
|
435
|
-
iterates over all its directories and for each one of them checks whether they
|
436
|
-
have a file called "erb.rb", or "erb.so", or "erb.o", or "erb.dll". If it finds
|
437
|
-
any of them, the interpreter loads it and ends the search. Otherwise, it tries
|
438
|
-
again in the next directory of the list. If the list gets exhausted, `LoadError`
|
439
|
-
is raised.
|
440
|
-
|
441
|
-
We are going to cover how constant autoloading works in more detail later, but
|
442
|
-
the idea is that when a constant like `Post` is hit and missing, if there's a
|
443
|
-
`post.rb` file for example in `app/models` Rails is going to find it, evaluate
|
444
|
-
it, and have `Post` defined as a side-effect.
|
445
|
-
|
446
|
-
Alright, Rails has a collection of directories similar to `$LOAD_PATH` in which
|
447
|
-
to look up `post.rb`. That collection is called `autoload_paths` and by
|
448
|
-
default it contains:
|
449
|
-
|
450
|
-
* All subdirectories of `app` in the application and engines. For example,
|
451
|
-
`app/controllers`. They do not need to be the default ones, any custom
|
452
|
-
directories like `app/workers` belong automatically to `autoload_paths`.
|
453
|
-
|
454
|
-
* Second level directories `app/{controllers,models}/concerns` in the
|
455
|
-
application and engines.
|
456
|
-
|
457
|
-
* The directory `test/mailers/previews`.
|
458
|
-
|
459
|
-
Also, this collection is configurable via `config.autoload_paths`. For example,
|
460
|
-
`lib` was in the list years ago, but no longer is. An application can opt-in
|
461
|
-
by adding this to `config/application.rb`:
|
462
|
-
|
463
|
-
```ruby
|
464
|
-
config.autoload_paths << "#{Rails.root}/lib"
|
465
|
-
```
|
466
|
-
`config.autoload_paths` is accessible from environment-specific configuration files, but any changes made to it outside `config/application.rb` don't have an effect.
|
467
|
-
|
468
|
-
The value of `autoload_paths` can be inspected. In a just generated application
|
469
|
-
it is (edited):
|
470
|
-
|
471
|
-
```
|
472
|
-
$ bin/rails r 'puts ActiveSupport::Dependencies.autoload_paths'
|
473
|
-
.../app/assets
|
474
|
-
.../app/controllers
|
475
|
-
.../app/helpers
|
476
|
-
.../app/mailers
|
477
|
-
.../app/models
|
478
|
-
.../app/controllers/concerns
|
479
|
-
.../app/models/concerns
|
480
|
-
.../test/mailers/previews
|
481
|
-
```
|
482
|
-
|
483
|
-
INFO. `autoload_paths` is computed and cached during the initialization process.
|
484
|
-
The application needs to be restarted to reflect any changes in the directory
|
485
|
-
structure.
|
486
|
-
|
487
|
-
|
488
|
-
Autoloading Algorithms
|
489
|
-
----------------------
|
490
|
-
|
491
|
-
### Relative References
|
492
|
-
|
493
|
-
A relative constant reference may appear in several places, for example, in
|
494
|
-
|
495
|
-
```ruby
|
496
|
-
class PostsController < ApplicationController
|
497
|
-
def index
|
498
|
-
@posts = Post.all
|
499
|
-
end
|
500
|
-
end
|
501
|
-
```
|
502
|
-
|
503
|
-
all three constant references are relative.
|
504
|
-
|
505
|
-
#### Constants after the `class` and `module` Keywords
|
506
|
-
|
507
|
-
Ruby performs a lookup for the constant that follows a `class` or `module`
|
508
|
-
keyword because it needs to know if the class or module is going to be created
|
509
|
-
or reopened.
|
510
|
-
|
511
|
-
If the constant is not defined at that point it is not considered to be a
|
512
|
-
missing constant, autoloading is **not** triggered.
|
513
|
-
|
514
|
-
So, in the previous example, if `PostsController` is not defined when the file
|
515
|
-
is interpreted Rails autoloading is not going to be triggered, Ruby will just
|
516
|
-
define the controller.
|
517
|
-
|
518
|
-
#### Top-Level Constants
|
519
|
-
|
520
|
-
On the contrary, if `ApplicationController` is unknown, the constant is
|
521
|
-
considered missing and an autoload is going to be attempted by Rails.
|
522
|
-
|
523
|
-
In order to load `ApplicationController`, Rails iterates over `autoload_paths`.
|
524
|
-
First checks if `app/assets/application_controller.rb` exists. If it does not,
|
525
|
-
which is normally the case, it continues and finds
|
526
|
-
`app/controllers/application_controller.rb`.
|
527
|
-
|
528
|
-
If the file defines the constant `ApplicationController` all is fine, otherwise
|
529
|
-
`LoadError` is raised:
|
530
|
-
|
531
|
-
```
|
532
|
-
unable to autoload constant ApplicationController, expected
|
533
|
-
<full path to application_controller.rb> to define it (LoadError)
|
534
|
-
```
|
535
|
-
|
536
|
-
INFO. Rails does not require the value of autoloaded constants to be a class or
|
537
|
-
module object. For example, if the file `app/models/max_clients.rb` defines
|
538
|
-
`MAX_CLIENTS = 100` autoloading `MAX_CLIENTS` works just fine.
|
539
|
-
|
540
|
-
#### Namespaces
|
541
|
-
|
542
|
-
Autoloading `ApplicationController` looks directly under the directories of
|
543
|
-
`autoload_paths` because the nesting in that spot is empty. The situation of
|
544
|
-
`Post` is different, the nesting in that line is `[PostsController]` and support
|
545
|
-
for namespaces comes into play.
|
546
|
-
|
547
|
-
The basic idea is that given
|
548
|
-
|
549
|
-
```ruby
|
550
|
-
module Admin
|
551
|
-
class BaseController < ApplicationController
|
552
|
-
@@all_roles = Role.all
|
553
|
-
end
|
554
|
-
end
|
555
|
-
```
|
556
|
-
|
557
|
-
to autoload `Role` we are going to check if it is defined in the current or
|
558
|
-
parent namespaces, one at a time. So, conceptually we want to try to autoload
|
559
|
-
any of
|
560
|
-
|
561
|
-
```
|
562
|
-
Admin::BaseController::Role
|
563
|
-
Admin::Role
|
564
|
-
Role
|
565
|
-
```
|
566
|
-
|
567
|
-
in that order. That's the idea. To do so, Rails looks in `autoload_paths`
|
568
|
-
respectively for file names like these:
|
569
|
-
|
570
|
-
```
|
571
|
-
admin/base_controller/role.rb
|
572
|
-
admin/role.rb
|
573
|
-
role.rb
|
574
|
-
```
|
575
|
-
|
576
|
-
modulus some additional directory lookups we are going to cover soon.
|
577
|
-
|
578
|
-
INFO. `'Constant::Name'.underscore` gives the relative path without extension of
|
579
|
-
the file name where `Constant::Name` is expected to be defined.
|
580
|
-
|
581
|
-
Let's see how Rails autoloads the `Post` constant in the `PostsController`
|
582
|
-
above assuming the application has a `Post` model defined in
|
583
|
-
`app/models/post.rb`.
|
584
|
-
|
585
|
-
First it checks for `posts_controller/post.rb` in `autoload_paths`:
|
586
|
-
|
587
|
-
```
|
588
|
-
app/assets/posts_controller/post.rb
|
589
|
-
app/controllers/posts_controller/post.rb
|
590
|
-
app/helpers/posts_controller/post.rb
|
591
|
-
...
|
592
|
-
test/mailers/previews/posts_controller/post.rb
|
593
|
-
```
|
594
|
-
|
595
|
-
Since the lookup is exhausted without success, a similar search for a directory
|
596
|
-
is performed, we are going to see why in the [next section](#automatic-modules):
|
597
|
-
|
598
|
-
```
|
599
|
-
app/assets/posts_controller/post
|
600
|
-
app/controllers/posts_controller/post
|
601
|
-
app/helpers/posts_controller/post
|
602
|
-
...
|
603
|
-
test/mailers/previews/posts_controller/post
|
604
|
-
```
|
605
|
-
|
606
|
-
If all those attempts fail, then Rails starts the lookup again in the parent
|
607
|
-
namespace. In this case only the top-level remains:
|
608
|
-
|
609
|
-
```
|
610
|
-
app/assets/post.rb
|
611
|
-
app/controllers/post.rb
|
612
|
-
app/helpers/post.rb
|
613
|
-
app/mailers/post.rb
|
614
|
-
app/models/post.rb
|
615
|
-
```
|
616
|
-
|
617
|
-
A matching file is found in `app/models/post.rb`. The lookup stops there and the
|
618
|
-
file is loaded. If the file actually defines `Post` all is fine, otherwise
|
619
|
-
`LoadError` is raised.
|
620
|
-
|
621
|
-
### Qualified References
|
622
|
-
|
623
|
-
When a qualified constant is missing Rails does not look for it in the parent
|
624
|
-
namespaces. But there is a caveat: When a constant is missing, Rails is
|
625
|
-
unable to tell if the trigger was a relative reference or a qualified one.
|
626
|
-
|
627
|
-
For example, consider
|
628
|
-
|
629
|
-
```ruby
|
630
|
-
module Admin
|
631
|
-
User
|
632
|
-
end
|
633
|
-
```
|
634
|
-
|
635
|
-
and
|
636
|
-
|
637
|
-
```ruby
|
638
|
-
Admin::User
|
639
|
-
```
|
640
|
-
|
641
|
-
If `User` is missing, in either case all Rails knows is that a constant called
|
642
|
-
"User" was missing in a module called "Admin".
|
643
|
-
|
644
|
-
If there is a top-level `User` Ruby would resolve it in the former example, but
|
645
|
-
wouldn't in the latter. In general, Rails does not emulate the Ruby constant
|
646
|
-
resolution algorithms, but in this case it tries using the following heuristic:
|
647
|
-
|
648
|
-
> If none of the parent namespaces of the class or module has the missing
|
649
|
-
> constant then Rails assumes the reference is relative. Otherwise qualified.
|
650
|
-
|
651
|
-
For example, if this code triggers autoloading
|
652
|
-
|
653
|
-
```ruby
|
654
|
-
Admin::User
|
655
|
-
```
|
656
|
-
|
657
|
-
and the `User` constant is already present in `Object`, it is not possible that
|
658
|
-
the situation is
|
659
|
-
|
660
|
-
```ruby
|
661
|
-
module Admin
|
662
|
-
User
|
663
|
-
end
|
664
|
-
```
|
665
|
-
|
666
|
-
because otherwise Ruby would have resolved `User` and no autoloading would have
|
667
|
-
been triggered in the first place. Thus, Rails assumes a qualified reference and
|
668
|
-
considers the file `admin/user.rb` and directory `admin/user` to be the only
|
669
|
-
valid options.
|
670
|
-
|
671
|
-
In practice, this works quite well as long as the nesting matches all parent
|
672
|
-
namespaces respectively and the constants that make the rule apply are known at
|
673
|
-
that time.
|
674
|
-
|
675
|
-
However, autoloading happens on demand. If by chance the top-level `User` was
|
676
|
-
not yet loaded, then Rails assumes a relative reference by contract.
|
677
|
-
|
678
|
-
Naming conflicts of this kind are rare in practice, but if one occurs,
|
679
|
-
`require_dependency` provides a solution by ensuring that the constant needed
|
680
|
-
to trigger the heuristic is defined in the conflicting place.
|
681
|
-
|
682
|
-
### Automatic Modules
|
683
|
-
|
684
|
-
When a module acts as a namespace, Rails does not require the application to
|
685
|
-
defines a file for it, a directory matching the namespace is enough.
|
686
|
-
|
687
|
-
Suppose an application has a back office whose controllers are stored in
|
688
|
-
`app/controllers/admin`. If the `Admin` module is not yet loaded when
|
689
|
-
`Admin::UsersController` is hit, Rails needs first to autoload the constant
|
690
|
-
`Admin`.
|
691
|
-
|
692
|
-
If `autoload_paths` has a file called `admin.rb` Rails is going to load that
|
693
|
-
one, but if there's no such file and a directory called `admin` is found, Rails
|
694
|
-
creates an empty module and assigns it to the `Admin` constant on the fly.
|
695
|
-
|
696
|
-
### Generic Procedure
|
697
|
-
|
698
|
-
Relative references are reported to be missing in the cref where they were hit,
|
699
|
-
and qualified references are reported to be missing in their parent (see
|
700
|
-
[Resolution Algorithm for Relative
|
701
|
-
Constants](#resolution-algorithm-for-relative-constants) at the beginning of
|
702
|
-
this guide for the definition of *cref*, and [Resolution Algorithm for Qualified
|
703
|
-
Constants](#resolution-algorithm-for-qualified-constants) for the definition of
|
704
|
-
*parent*).
|
705
|
-
|
706
|
-
The procedure to autoload constant `C` in an arbitrary situation is as follows:
|
707
|
-
|
708
|
-
```
|
709
|
-
if the class or module in which C is missing is Object
|
710
|
-
let ns = ''
|
711
|
-
else
|
712
|
-
let M = the class or module in which C is missing
|
713
|
-
|
714
|
-
if M is anonymous
|
715
|
-
let ns = ''
|
716
|
-
else
|
717
|
-
let ns = M.name
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
loop do
|
722
|
-
# Look for a regular file.
|
723
|
-
for dir in autoload_paths
|
724
|
-
if the file "#{dir}/#{ns.underscore}/c.rb" exists
|
725
|
-
load/require "#{dir}/#{ns.underscore}/c.rb"
|
726
|
-
|
727
|
-
if C is now defined
|
728
|
-
return
|
729
|
-
else
|
730
|
-
raise LoadError
|
731
|
-
end
|
732
|
-
end
|
733
|
-
end
|
734
|
-
|
735
|
-
# Look for an automatic module.
|
736
|
-
for dir in autoload_paths
|
737
|
-
if the directory "#{dir}/#{ns.underscore}/c" exists
|
738
|
-
if ns is an empty string
|
739
|
-
let C = Module.new in Object and return
|
740
|
-
else
|
741
|
-
let C = Module.new in ns.constantize and return
|
742
|
-
end
|
743
|
-
end
|
744
|
-
end
|
745
|
-
|
746
|
-
if ns is empty
|
747
|
-
# We reached the top-level without finding the constant.
|
748
|
-
raise NameError
|
749
|
-
else
|
750
|
-
if C exists in any of the parent namespaces
|
751
|
-
# Qualified constants heuristic.
|
752
|
-
raise NameError
|
753
|
-
else
|
754
|
-
# Try again in the parent namespace.
|
755
|
-
let ns = the parent namespace of ns and retry
|
756
|
-
end
|
757
|
-
end
|
758
|
-
end
|
759
|
-
```
|
760
|
-
|
761
|
-
|
762
|
-
require_dependency
|
763
|
-
------------------
|
764
|
-
|
765
|
-
Constant autoloading is triggered on demand and therefore code that uses a
|
766
|
-
certain constant may have it already defined or may trigger an autoload. That
|
767
|
-
depends on the execution path and it may vary between runs.
|
768
|
-
|
769
|
-
There are times, however, in which you want to make sure a certain constant is
|
770
|
-
known when the execution reaches some code. `require_dependency` provides a way
|
771
|
-
to load a file using the current [loading mechanism](#loading-mechanism), and
|
772
|
-
keeping track of constants defined in that file as if they were autoloaded to
|
773
|
-
have them reloaded as needed.
|
774
|
-
|
775
|
-
`require_dependency` is rarely needed, but see a couple of use-cases in
|
776
|
-
[Autoloading and STI](#autoloading-and-sti) and [When Constants aren't
|
777
|
-
Triggered](#when-constants-aren-t-missed).
|
778
|
-
|
779
|
-
WARNING. Unlike autoloading, `require_dependency` does not expect the file to
|
780
|
-
define any particular constant. Exploiting this behavior would be a bad practice
|
781
|
-
though, file and constant paths should match.
|
782
|
-
|
783
|
-
|
784
|
-
Constant Reloading
|
785
|
-
------------------
|
786
|
-
|
787
|
-
When `config.cache_classes` is false Rails is able to reload autoloaded
|
788
|
-
constants.
|
789
|
-
|
790
|
-
For example, in you're in a console session and edit some file behind the
|
791
|
-
scenes, the code can be reloaded with the `reload!` command:
|
792
|
-
|
793
|
-
```
|
794
|
-
> reload!
|
795
|
-
```
|
796
|
-
|
797
|
-
When the application runs, code is reloaded when something relevant to this
|
798
|
-
logic changes. In order to do that, Rails monitors a number of things:
|
799
|
-
|
800
|
-
* `config/routes.rb`.
|
801
|
-
|
802
|
-
* Locales.
|
803
|
-
|
804
|
-
* Ruby files under `autoload_paths`.
|
805
|
-
|
806
|
-
* `db/schema.rb` and `db/structure.sql`.
|
807
|
-
|
808
|
-
If anything in there changes, there is a middleware that detects it and reloads
|
809
|
-
the code.
|
810
|
-
|
811
|
-
Autoloading keeps track of autoloaded constants. Reloading is implemented by
|
812
|
-
removing them all from their respective classes and modules using
|
813
|
-
`Module#remove_const`. That way, when the code goes on, those constants are
|
814
|
-
going to be unknown again, and files reloaded on demand.
|
815
|
-
|
816
|
-
INFO. This is an all-or-nothing operation, Rails does not attempt to reload only
|
817
|
-
what changed since dependencies between classes makes that really tricky.
|
818
|
-
Instead, everything is wiped.
|
819
|
-
|
820
|
-
|
821
|
-
Module#autoload isn't Involved
|
822
|
-
------------------------------
|
823
|
-
|
824
|
-
`Module#autoload` provides a lazy way to load constants that is fully integrated
|
825
|
-
with the Ruby constant lookup algorithms, dynamic constant API, etc. It is quite
|
826
|
-
transparent.
|
827
|
-
|
828
|
-
Rails internals make extensive use of it to defer as much work as possible from
|
829
|
-
the boot process. But constant autoloading in Rails is **not** implemented with
|
830
|
-
`Module#autoload`.
|
831
|
-
|
832
|
-
One possible implementation based on `Module#autoload` would be to walk the
|
833
|
-
application tree and issue `autoload` calls that map existing file names to
|
834
|
-
their conventional constant name.
|
835
|
-
|
836
|
-
There are a number of reasons that prevent Rails from using that implementation.
|
837
|
-
|
838
|
-
For example, `Module#autoload` is only capable of loading files using `require`,
|
839
|
-
so reloading would not be possible. Not only that, it uses an internal `require`
|
840
|
-
which is not `Kernel#require`.
|
841
|
-
|
842
|
-
Then, it provides no way to remove declarations in case a file is deleted. If a
|
843
|
-
constant gets removed with `Module#remove_const` its `autoload` is not triggered
|
844
|
-
again. Also, it doesn't support qualified names, so files with namespaces should
|
845
|
-
be interpreted during the walk tree to install their own `autoload` calls, but
|
846
|
-
those files could have constant references not yet configured.
|
847
|
-
|
848
|
-
An implementation based on `Module#autoload` would be awesome but, as you see,
|
849
|
-
at least as of today it is not possible. Constant autoloading in Rails is
|
850
|
-
implemented with `Module#const_missing`, and that's why it has its own contract,
|
851
|
-
documented in this guide.
|
852
|
-
|
853
|
-
|
854
|
-
Common Gotchas
|
855
|
-
--------------
|
856
|
-
|
857
|
-
### Nesting and Qualified Constants
|
858
|
-
|
859
|
-
Let's consider
|
860
|
-
|
861
|
-
```ruby
|
862
|
-
module Admin
|
863
|
-
class UsersController < ApplicationController
|
864
|
-
def index
|
865
|
-
@users = User.all
|
866
|
-
end
|
867
|
-
end
|
868
|
-
end
|
869
|
-
```
|
870
|
-
|
871
|
-
and
|
872
|
-
|
873
|
-
```ruby
|
874
|
-
class Admin::UsersController < ApplicationController
|
875
|
-
def index
|
876
|
-
@users = User.all
|
877
|
-
end
|
878
|
-
end
|
879
|
-
```
|
880
|
-
|
881
|
-
To resolve `User` Ruby checks `Admin` in the former case, but it does not in
|
882
|
-
the latter because it does not belong to the nesting (see [Nesting](#nesting)
|
883
|
-
and [Resolution Algorithms](#resolution-algorithms)).
|
884
|
-
|
885
|
-
Unfortunately Rails autoloading does not know the nesting in the spot where the
|
886
|
-
constant was missing and so it is not able to act as Ruby would. In particular,
|
887
|
-
`Admin::User` will get autoloaded in either case.
|
888
|
-
|
889
|
-
Albeit qualified constants with `class` and `module` keywords may technically
|
890
|
-
work with autoloading in some cases, it is preferable to use relative constants
|
891
|
-
instead:
|
892
|
-
|
893
|
-
```ruby
|
894
|
-
module Admin
|
895
|
-
class UsersController < ApplicationController
|
896
|
-
def index
|
897
|
-
@users = User.all
|
898
|
-
end
|
899
|
-
end
|
900
|
-
end
|
901
|
-
```
|
902
|
-
|
903
|
-
### Autoloading and STI
|
904
|
-
|
905
|
-
Single Table Inheritance (STI) is a feature of Active Record that enables
|
906
|
-
storing a hierarchy of models in one single table. The API of such models is
|
907
|
-
aware of the hierarchy and encapsulates some common needs. For example, given
|
908
|
-
these classes:
|
909
|
-
|
910
|
-
```ruby
|
911
|
-
# app/models/polygon.rb
|
912
|
-
class Polygon < ActiveRecord::Base
|
913
|
-
end
|
914
|
-
|
915
|
-
# app/models/triangle.rb
|
916
|
-
class Triangle < Polygon
|
917
|
-
end
|
918
|
-
|
919
|
-
# app/models/rectangle.rb
|
920
|
-
class Rectangle < Polygon
|
921
|
-
end
|
922
|
-
```
|
923
|
-
|
924
|
-
`Triangle.create` creates a row that represents a triangle, and
|
925
|
-
`Rectangle.create` creates a row that represents a rectangle. If `id` is the
|
926
|
-
ID of an existing record, `Polygon.find(id)` returns an object of the correct
|
927
|
-
type.
|
928
|
-
|
929
|
-
Methods that operate on collections are also aware of the hierarchy. For
|
930
|
-
example, `Polygon.all` returns all the records of the table, because all
|
931
|
-
rectangles and triangles are polygons. Active Record takes care of returning
|
932
|
-
instances of their corresponding class in the result set.
|
933
|
-
|
934
|
-
Types are autoloaded as needed. For example, if `Polygon.first` is a rectangle
|
935
|
-
and `Rectangle` has not yet been loaded, Active Record autoloads it and the
|
936
|
-
record is correctly instantiated.
|
937
|
-
|
938
|
-
All good, but if instead of performing queries based on the root class we need
|
939
|
-
to work on some subclass, things get interesting.
|
940
|
-
|
941
|
-
While working with `Polygon` you do not need to be aware of all its descendants,
|
942
|
-
because anything in the table is by definition a polygon, but when working with
|
943
|
-
subclasses Active Record needs to be able to enumerate the types it is looking
|
944
|
-
for. Let’s see an example.
|
945
|
-
|
946
|
-
`Rectangle.all` only loads rectangles by adding a type constraint to the query:
|
947
|
-
|
948
|
-
```sql
|
949
|
-
SELECT "polygons".* FROM "polygons"
|
950
|
-
WHERE "polygons"."type" IN ("Rectangle")
|
951
|
-
```
|
952
|
-
|
953
|
-
Let’s introduce now a subclass of `Rectangle`:
|
954
|
-
|
955
|
-
```ruby
|
956
|
-
# app/models/square.rb
|
957
|
-
class Square < Rectangle
|
958
|
-
end
|
959
|
-
```
|
960
|
-
|
961
|
-
`Rectangle.all` should now return rectangles **and** squares:
|
962
|
-
|
963
|
-
```sql
|
964
|
-
SELECT "polygons".* FROM "polygons"
|
965
|
-
WHERE "polygons"."type" IN ("Rectangle", "Square")
|
966
|
-
```
|
967
|
-
|
968
|
-
But there’s a caveat here: How does Active Record know that the class `Square`
|
969
|
-
exists at all?
|
970
|
-
|
971
|
-
Even if the file `app/models/square.rb` exists and defines the `Square` class,
|
972
|
-
if no code yet used that class, `Rectangle.all` issues the query
|
973
|
-
|
974
|
-
```sql
|
975
|
-
SELECT "polygons".* FROM "polygons"
|
976
|
-
WHERE "polygons"."type" IN ("Rectangle")
|
977
|
-
```
|
978
|
-
|
979
|
-
That is not a bug, the query includes all *known* descendants of `Rectangle`.
|
980
|
-
|
981
|
-
A way to ensure this works correctly regardless of the order of execution is to
|
982
|
-
load the leaves of the tree by hand at the bottom of the file that defines the
|
983
|
-
root class:
|
984
|
-
|
985
|
-
```ruby
|
986
|
-
# app/models/polygon.rb
|
987
|
-
class Polygon < ActiveRecord::Base
|
988
|
-
end
|
989
|
-
require_dependency ‘square’
|
990
|
-
```
|
991
|
-
|
992
|
-
Only the leaves that are **at least grandchildren** need to be loaded this
|
993
|
-
way. Direct subclasses do not need to be preloaded. If the hierarchy is
|
994
|
-
deeper, intermediate classes will be autoloaded recursively from the bottom
|
995
|
-
because their constant will appear in the class definitions as superclass.
|
996
|
-
|
997
|
-
### Autoloading and `require`
|
998
|
-
|
999
|
-
Files defining constants to be autoloaded should never be `require`d:
|
1000
|
-
|
1001
|
-
```ruby
|
1002
|
-
require 'user' # DO NOT DO THIS
|
1003
|
-
|
1004
|
-
class UsersController < ApplicationController
|
1005
|
-
...
|
1006
|
-
end
|
1007
|
-
```
|
1008
|
-
|
1009
|
-
There are two possible gotchas here in development mode:
|
1010
|
-
|
1011
|
-
1. If `User` is autoloaded before reaching the `require`, `app/models/user.rb`
|
1012
|
-
runs again because `load` does not update `$LOADED_FEATURES`.
|
1013
|
-
|
1014
|
-
2. If the `require` runs first Rails does not mark `User` as an autoloaded
|
1015
|
-
constant and changes to `app/models/user.rb` aren't reloaded.
|
1016
|
-
|
1017
|
-
Just follow the flow and use constant autoloading always, never mix
|
1018
|
-
autoloading and `require`. As a last resort, if some file absolutely needs to
|
1019
|
-
load a certain file use `require_dependency` to play nice with constant
|
1020
|
-
autoloading. This option is rarely needed in practice, though.
|
1021
|
-
|
1022
|
-
Of course, using `require` in autoloaded files to load ordinary 3rd party
|
1023
|
-
libraries is fine, and Rails is able to distinguish their constants, they are
|
1024
|
-
not marked as autoloaded.
|
1025
|
-
|
1026
|
-
### Autoloading and Initializers
|
1027
|
-
|
1028
|
-
Consider this assignment in `config/initializers/set_auth_service.rb`:
|
1029
|
-
|
1030
|
-
```ruby
|
1031
|
-
AUTH_SERVICE = if Rails.env.production?
|
1032
|
-
RealAuthService
|
1033
|
-
else
|
1034
|
-
MockedAuthService
|
1035
|
-
end
|
1036
|
-
```
|
1037
|
-
|
1038
|
-
The purpose of this setup would be that the application uses the class that
|
1039
|
-
corresponds to the environment via `AUTH_SERVICE`. In development mode
|
1040
|
-
`MockedAuthService` gets autoloaded when the initializer runs. Let’s suppose
|
1041
|
-
we do some requests, change its implementation, and hit the application again.
|
1042
|
-
To our surprise the changes are not reflected. Why?
|
1043
|
-
|
1044
|
-
As [we saw earlier](#constant-reloading), Rails removes autoloaded constants,
|
1045
|
-
but `AUTH_SERVICE` stores the original class object. Stale, non-reachable
|
1046
|
-
using the original constant, but perfectly functional.
|
1047
|
-
|
1048
|
-
The following code summarizes the situation:
|
1049
|
-
|
1050
|
-
```ruby
|
1051
|
-
class C
|
1052
|
-
def quack
|
1053
|
-
'quack!'
|
1054
|
-
end
|
1055
|
-
end
|
1056
|
-
|
1057
|
-
X = C
|
1058
|
-
Object.instance_eval { remove_const(:C) }
|
1059
|
-
X.new.quack # => quack!
|
1060
|
-
X.name # => C
|
1061
|
-
C # => uninitialized constant C (NameError)
|
1062
|
-
```
|
1063
|
-
|
1064
|
-
Because of that, it is not a good idea to autoload constants on application
|
1065
|
-
initialization.
|
1066
|
-
|
1067
|
-
In the case above we could implement a dynamic access point:
|
1068
|
-
|
1069
|
-
```ruby
|
1070
|
-
# app/models/auth_service.rb
|
1071
|
-
class AuthService
|
1072
|
-
if Rails.env.production?
|
1073
|
-
def self.instance
|
1074
|
-
RealAuthService
|
1075
|
-
end
|
1076
|
-
else
|
1077
|
-
def self.instance
|
1078
|
-
MockedAuthService
|
1079
|
-
end
|
1080
|
-
end
|
1081
|
-
end
|
1082
|
-
```
|
1083
|
-
|
1084
|
-
and have the application use `AuthService.instance` instead. `AuthService`
|
1085
|
-
would be loaded on demand and be autoload-friendly.
|
1086
|
-
|
1087
|
-
### `require_dependency` and Initializers
|
1088
|
-
|
1089
|
-
As we saw before, `require_dependency` loads files in an autoloading-friendly
|
1090
|
-
way. Normally, though, such a call does not make sense in an initializer.
|
1091
|
-
|
1092
|
-
One could think about doing some [`require_dependency`](#require-dependency)
|
1093
|
-
calls in an initializer to make sure certain constants are loaded upfront, for
|
1094
|
-
example as an attempt to address the [gotcha with STIs](#autoloading-and-sti).
|
1095
|
-
|
1096
|
-
Problem is, in development mode [autoloaded constants are wiped](#constant-reloading)
|
1097
|
-
if there is any relevant change in the file system. If that happens then
|
1098
|
-
we are in the very same situation the initializer wanted to avoid!
|
1099
|
-
|
1100
|
-
Calls to `require_dependency` have to be strategically written in autoloaded
|
1101
|
-
spots.
|
1102
|
-
|
1103
|
-
### When Constants aren't Missed
|
1104
|
-
|
1105
|
-
#### Relative References
|
1106
|
-
|
1107
|
-
Let's consider a flight simulator. The application has a default flight model
|
1108
|
-
|
1109
|
-
```ruby
|
1110
|
-
# app/models/flight_model.rb
|
1111
|
-
class FlightModel
|
1112
|
-
end
|
1113
|
-
```
|
1114
|
-
|
1115
|
-
that can be overridden by each airplane, for instance
|
1116
|
-
|
1117
|
-
```ruby
|
1118
|
-
# app/models/bell_x1/flight_model.rb
|
1119
|
-
module BellX1
|
1120
|
-
class FlightModel < FlightModel
|
1121
|
-
end
|
1122
|
-
end
|
1123
|
-
|
1124
|
-
# app/models/bell_x1/aircraft.rb
|
1125
|
-
module BellX1
|
1126
|
-
class Aircraft
|
1127
|
-
def initialize
|
1128
|
-
@flight_model = FlightModel.new
|
1129
|
-
end
|
1130
|
-
end
|
1131
|
-
end
|
1132
|
-
```
|
1133
|
-
|
1134
|
-
The initializer wants to create a `BellX1::FlightModel` and nesting has
|
1135
|
-
`BellX1`, that looks good. But if the default flight model is loaded and the
|
1136
|
-
one for the Bell-X1 is not, the interpreter is able to resolve the top-level
|
1137
|
-
`FlightModel` and autoloading is thus not triggered for `BellX1::FlightModel`.
|
1138
|
-
|
1139
|
-
That code depends on the execution path.
|
1140
|
-
|
1141
|
-
These kind of ambiguities can often be resolved using qualified constants:
|
1142
|
-
|
1143
|
-
```ruby
|
1144
|
-
module BellX1
|
1145
|
-
class Plane
|
1146
|
-
def flight_model
|
1147
|
-
@flight_model ||= BellX1::FlightModel.new
|
1148
|
-
end
|
1149
|
-
end
|
1150
|
-
end
|
1151
|
-
```
|
1152
|
-
|
1153
|
-
Also, `require_dependency` is a solution:
|
1154
|
-
|
1155
|
-
```ruby
|
1156
|
-
require_dependency 'bell_x1/flight_model'
|
1157
|
-
|
1158
|
-
module BellX1
|
1159
|
-
class Plane
|
1160
|
-
def flight_model
|
1161
|
-
@flight_model ||= FlightModel.new
|
1162
|
-
end
|
1163
|
-
end
|
1164
|
-
end
|
1165
|
-
```
|
1166
|
-
|
1167
|
-
#### Qualified References
|
1168
|
-
|
1169
|
-
Given
|
1170
|
-
|
1171
|
-
```ruby
|
1172
|
-
# app/models/hotel.rb
|
1173
|
-
class Hotel
|
1174
|
-
end
|
1175
|
-
|
1176
|
-
# app/models/image.rb
|
1177
|
-
class Image
|
1178
|
-
end
|
1179
|
-
|
1180
|
-
# app/models/hotel/image.rb
|
1181
|
-
class Hotel
|
1182
|
-
class Image < Image
|
1183
|
-
end
|
1184
|
-
end
|
1185
|
-
```
|
1186
|
-
|
1187
|
-
the expression `Hotel::Image` is ambiguous because it depends on the execution
|
1188
|
-
path.
|
1189
|
-
|
1190
|
-
As [we saw before](#resolution-algorithm-for-qualified-constants), Ruby looks
|
1191
|
-
up the constant in `Hotel` and its ancestors. If `app/models/image.rb` has
|
1192
|
-
been loaded but `app/models/hotel/image.rb` hasn't, Ruby does not find `Image`
|
1193
|
-
in `Hotel`, but it does in `Object`:
|
1194
|
-
|
1195
|
-
```
|
1196
|
-
$ bin/rails r 'Image; p Hotel::Image' 2>/dev/null
|
1197
|
-
Image # NOT Hotel::Image!
|
1198
|
-
```
|
1199
|
-
|
1200
|
-
The code evaluating `Hotel::Image` needs to make sure
|
1201
|
-
`app/models/hotel/image.rb` has been loaded, possibly with
|
1202
|
-
`require_dependency`.
|
1203
|
-
|
1204
|
-
In these cases the interpreter issues a warning though:
|
1205
|
-
|
1206
|
-
```
|
1207
|
-
warning: toplevel constant Image referenced by Hotel::Image
|
1208
|
-
```
|
1209
|
-
|
1210
|
-
This surprising constant resolution can be observed with any qualifying class:
|
1211
|
-
|
1212
|
-
```
|
1213
|
-
2.1.5 :001 > String::Array
|
1214
|
-
(irb):1: warning: toplevel constant Array referenced by String::Array
|
1215
|
-
=> Array
|
1216
|
-
```
|
1217
|
-
|
1218
|
-
WARNING. To find this gotcha the qualifying namespace has to be a class,
|
1219
|
-
`Object` is not an ancestor of modules.
|
1220
|
-
|
1221
|
-
### Autoloading within Singleton Classes
|
1222
|
-
|
1223
|
-
Let's suppose we have these class definitions:
|
1224
|
-
|
1225
|
-
```ruby
|
1226
|
-
# app/models/hotel/services.rb
|
1227
|
-
module Hotel
|
1228
|
-
class Services
|
1229
|
-
end
|
1230
|
-
end
|
1231
|
-
|
1232
|
-
# app/models/hotel/geo_location.rb
|
1233
|
-
module Hotel
|
1234
|
-
class GeoLocation
|
1235
|
-
class << self
|
1236
|
-
Services
|
1237
|
-
end
|
1238
|
-
end
|
1239
|
-
end
|
1240
|
-
```
|
1241
|
-
|
1242
|
-
If `Hotel::Services` is known by the time `app/models/hotel/geo_location.rb`
|
1243
|
-
is being loaded, `Services` is resolved by Ruby because `Hotel` belongs to the
|
1244
|
-
nesting when the singleton class of `Hotel::GeoLocation` is opened.
|
1245
|
-
|
1246
|
-
But if `Hotel::Services` is not known, Rails is not able to autoload it, the
|
1247
|
-
application raises `NameError`.
|
1248
|
-
|
1249
|
-
The reason is that autoloading is triggered for the singleton class, which is
|
1250
|
-
anonymous, and as [we saw before](#generic-procedure), Rails only checks the
|
1251
|
-
top-level namespace in that edge case.
|
1252
|
-
|
1253
|
-
An easy solution to this caveat is to qualify the constant:
|
1254
|
-
|
1255
|
-
```ruby
|
1256
|
-
module Hotel
|
1257
|
-
class GeoLocation
|
1258
|
-
class << self
|
1259
|
-
Hotel::Services
|
1260
|
-
end
|
1261
|
-
end
|
1262
|
-
end
|
1263
|
-
```
|
1264
|
-
|
1265
|
-
### Autoloading in `BasicObject`
|
1266
|
-
|
1267
|
-
Direct descendants of `BasicObject` do not have `Object` among their ancestors
|
1268
|
-
and cannot resolve top-level constants:
|
1269
|
-
|
1270
|
-
```ruby
|
1271
|
-
class C < BasicObject
|
1272
|
-
String # NameError: uninitialized constant C::String
|
1273
|
-
end
|
1274
|
-
```
|
1275
|
-
|
1276
|
-
When autoloading is involved that plot has a twist. Let's consider:
|
1277
|
-
|
1278
|
-
```ruby
|
1279
|
-
class C < BasicObject
|
1280
|
-
def user
|
1281
|
-
User # WRONG
|
1282
|
-
end
|
1283
|
-
end
|
1284
|
-
```
|
1285
|
-
|
1286
|
-
Since Rails checks the top-level namespace `User` gets autoloaded just fine the
|
1287
|
-
first time the `user` method is invoked. You only get the exception if the
|
1288
|
-
`User` constant is known at that point, in particular in a *second* call to
|
1289
|
-
`user`:
|
1290
|
-
|
1291
|
-
```ruby
|
1292
|
-
c = C.new
|
1293
|
-
c.user # surprisingly fine, User
|
1294
|
-
c.user # NameError: uninitialized constant C::User
|
1295
|
-
```
|
1296
|
-
|
1297
|
-
because it detects that a parent namespace already has the constant (see [Qualified
|
1298
|
-
References](#autoloading-algorithms-qualified-references)).
|
1299
|
-
|
1300
|
-
As with pure Ruby, within the body of a direct descendant of `BasicObject` use
|
1301
|
-
always absolute constant paths:
|
1302
|
-
|
1303
|
-
```ruby
|
1304
|
-
class C < BasicObject
|
1305
|
-
::String # RIGHT
|
1306
|
-
|
1307
|
-
def user
|
1308
|
-
::User # RIGHT
|
1309
|
-
end
|
1310
|
-
end
|
1311
|
-
```
|