aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/constant_autoloading_and_reloading.md
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2014-12-19 19:40:33 +0100
committerXavier Noria <fxn@hashref.com>2014-12-19 19:50:24 +0100
commit352680c1d394a2177437f20673ede0753d651913 (patch)
treec6d813cc514e965fade11ad89300e0f380f0ca94 /guides/source/constant_autoloading_and_reloading.md
parent86637391db35be25825b26e4f014d47f6a7478ae (diff)
downloadrails-352680c1d394a2177437f20673ede0753d651913.tar.gz
rails-352680c1d394a2177437f20673ede0753d651913.tar.bz2
rails-352680c1d394a2177437f20673ede0753d651913.zip
last pass to the autoloading guide before release [ci skip]
Diffstat (limited to 'guides/source/constant_autoloading_and_reloading.md')
-rw-r--r--guides/source/constant_autoloading_and_reloading.md61
1 files changed, 44 insertions, 17 deletions
diff --git a/guides/source/constant_autoloading_and_reloading.md b/guides/source/constant_autoloading_and_reloading.md
index 15f2141b99..c616138898 100644
--- a/guides/source/constant_autoloading_and_reloading.md
+++ b/guides/source/constant_autoloading_and_reloading.md
@@ -20,7 +20,7 @@ Introduction
Ruby on Rails allows applications to be written as if their code was preloaded.
-In a normal Ruby program a class needs to load its dependencies:
+In a normal Ruby program classes need to load their dependencies:
```ruby
require 'application_controller'
@@ -97,12 +97,14 @@ class XML::SAXParser
end
```
-the nesting in (2) is different, `XML` does not belong to it:
+the nesting in (2) is different:
```ruby
[XML::SAXParser]
```
+`XML` does not belong to it.
+
We can see in this example that the name of a class or module that belongs to a
certain nesting does not necessarily correlate with the namespaces at the spot.
@@ -177,6 +179,21 @@ performs a constant assignment equivalent to
Project = Class.new(ActiveRecord::Base)
```
+including setting the name of the class as a side-effect:
+
+```ruby
+Project.name # => "Project"
+```
+
+Constant assignment has a special rule to make that happen: if the object
+being assigned is an anonymous class or module, Ruby sets its name to be the
+one the constant.
+
+INFO. From then on, what happens to the constant and the instance does not
+matter. For example, the constant could be deleted, the class object could be
+assigned to a different constant, be stored in no constant anymore, etc. Once
+the name is set, it doesn't change.
+
Similarly, module creation using the `module` keyword as in
```ruby
@@ -190,16 +207,21 @@ performs a constant assignment equivalent to
Admin = Module.new
```
+including setting the name as a side-effect:
+
+```ruby
+Admin.name # => "Admin"
+```
+
WARNING. The execution context of a block passed to `Class.new` or `Module.new`
is not entirely equivalent to the one of the body of the definitions using the
`class` and `module` keywords. But both idioms result in the same constant
assignment.
Thus, when one informally says "the `String` class", that really means: the
-class object the interpreter creates and stores in a constant called "String" in
-the class object stored in the `Object` constant. `String` is otherwise an
-ordinary Ruby constant and everything related to constants applies to it,
-resolution algorithms, etc.
+class object stored in the constant called "String" in the class object stored
+in the `Object` constant. `String` is otherwise an ordinary Ruby constant and
+everything related to constants applies to it, resolution algorithms, etc.
Likewise, in the controller
@@ -214,17 +236,17 @@ end
`Post` is not syntax for a class. Rather, `Post` is a regular Ruby constant. If
all is good, the constant evaluates to an object that responds to `all`.
-That is why we talk about *constant autoloading*, Rails has the ability to load
-constants on the fly.
+That is why we talk about *constant* autoloading, Rails has the ability to
+load constants on the fly.
### Constants are Stored in Modules
Constants belong to modules in a very literal sense. Classes and modules have
a constant table; think of it as a hash table.
-Let's analyze an example to really understand what that means. While in a
-casual setting some abuses of language are customary, the exposition is going
-to be exact here for didactic purposes.
+Let's analyze an example to really understand what that means. While common
+abuses of language like "the `String` class" are convenient, the exposition is
+going to be precise here for didactic purposes.
Let's consider the following module definition:
@@ -283,10 +305,16 @@ Billing::Invoice
```
`Billing::Invoice` is composed of two constants: `Billing` is relative and is
-resolved using the algorithm of the previous section; `Invoice` is qualified by
-`Billing` and we are going to see its resolution next. Let's call *parent* to
-that qualifying class or module object, that is, `Billing` in the example above.
-The algorithm for qualified constants goes like this:
+resolved using the algorithm of the previous section.
+
+INFO. Leading colons would make the first segment absolute rather than
+relative: `::Billing::Invoice`. That would force `Billing` to be looked up
+only as a top-level constant.
+
+`Invoice` on the other hand is qualified by `Billing` and we are going to see
+its resolution next. Let's call *parent* to that qualifying class or module
+object, that is, `Billing` in the example above. The algorithm for qualified
+constants goes like this:
1. The constant is looked up in the parent and its ancestors.
@@ -632,8 +660,7 @@ namespaces respectively and the constants that make the rule apply are known at
that time.
However, autoloading happens on demand. If by chance the top-level `User` was
-not yet loaded, then Rails has no way to know whether `Admin::User` should load
-it or raise `NameError`.
+not yet loaded, then Rails assumes a relative reference by contract.
Naming conflicts of this kind are rare in practice, but if one occurs,
`require_dependency` provides a solution by ensuring that the constant needed