Skip to content

Commit 69eb637

Browse files
committed
moar words
1 parent 5c57b8e commit 69eb637

File tree

2 files changed

+63
-11
lines changed

2 files changed

+63
-11
lines changed

_posts/2020-01-23-farewell-rails-autoloading.md

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,72 @@
11
---
22
layout: post
33
author: Tony Schneider
4-
title : Farewell Rails Autoloading
4+
title : Classic Rails Autoloading - Eigenclasses
55
date : 2020-01-23
66
tags : software
7-
published: false
87
---
98

9+
Rails constant autoloading is a really nifty feature.
10+
11+
It lets us reference constants without explicitly requiring them.
12+
It is also what allows Rails to pick up changes to files without having to constantly restart your server.
13+
14+
It's one of those features that goes under appreciated.
15+
If it's working you probably don't even know it's there -- until something goes wrong :laughing:
16+
17+
One gotcha I've run into a number of times is how it interacts with Ruby's `class << self` syntax.
18+
19+
## 10,000 Foot View
20+
21+
When you write Ruby code, you are likely defining lots of constants.
22+
Module names are constants, class names are constants, and of course constants are constants!
23+
24+
When you run the code, Ruby expects you to have defined the constants you use.
25+
Typically this is done by requiring the ruby file(s) that you plan to use.
26+
27+
```ruby
28+
# in foo.rb
29+
class Foo
30+
end
31+
32+
# in bar.rb
33+
require "foo"
34+
Foo.new
35+
```
36+
37+
If we were to reference `Foo` in `bar.rb` without the `require "foo"`, ruby would call `const_missing`.
38+
Without any further intervention, it would raise an... uninitialized constant error a la `NameError (uninitialized constant Foo)`
39+
40+
Rails autoloading works by hooking into the ruby hook `const_missing` and relying on autoloading _conventions_ to figure out where to find the missing constant.
41+
1042
## First some Ruby
1143

12-
Rails autoloading works by hooking into the ruby hook const_missing.
13-
You run some code, Ruby’s like what’s that, rails is like, “I got you, I’ve implemented const_missing” and walks up the module hierarchy and requires the file that constant should be defined in by rails convention.
44+
```ruby
45+
class YourClass
46+
class << self
47+
def your_method
48+
"Hi there"
49+
end
50+
end
51+
end
52+
53+
YourClass.your_method # => Hi there
54+
```
1455

15-
However, the `class << self` syntax isn’t simply an alternate syntax for defining class methods.
56+
The `class << self` syntax isn’t simply an alternate syntax for defining class methods.
1657
While ultimately it results in a class method, you’re doing so by opening the class’s "eigenclass".
17-
Eigen just means self in german or whatever.
58+
59+
Sounds intimidating, but _Eigen_ just means "self" in German.
1860
I think it's easier to reason about when referred to as a "singleton class".
1961

2062
In the ruby object model you have classes and instances of those classes.
21-
A user defined class is just an instance of the class Class (whew).
22-
So, if you're curious you might wonder how ruby keeps track of class methods vs instance methods.
63+
A user defined class is just an instance of the class Class (whew :sweat_smile:).
2364

65+
If you're curious, you might wonder how ruby keeps track of class methods vs instance methods.
2466
The answer is that each class has an anonymous singleton class.
67+
2568
You can actually see it by doing `YourClass.singleton_class`.
69+
2670
The class methods you define (regardless of how) end up as instance methods of the singleton class, as opposed to instance methods on the class you defined.
2771

2872
```
@@ -44,9 +88,11 @@ class A
4488
Module.nesting
4589
end
4690
end
91+
4792
def self.bar
4893
Module.nesting
4994
end
95+
5096
def baz
5197
Module.nesting
5298
end
@@ -61,7 +107,7 @@ In Rails 5, here is roughly how the "classic" autoloading algorithm works: https
61107

62108
So let's go to an example you might see in the wild:
63109

64-
```
110+
```ruby
65111
module SomeEngine
66112
module SomeNamespace
67113
class PolicyService
@@ -79,7 +125,7 @@ module SomeEngine
79125
end
80126
```
81127

82-
As defined, the nesting inside `PolicyService.create_policy` is `[#<Class:SomeEngine::SomeNamespace::PolicyService>, SomeEngine::SomeNamespace::PolicyService]`.
128+
As defined, the nesting inside `PolicyService.create_policy` is: `[#<Class:SomeEngine::SomeNamespace::PolicyService>, SomeEngine::SomeNamespace::PolicyService]`.
83129

84130
Same as the earlier example, the nesting for `PolicyService.create_policy2` is `[SomeEngine::SomeNamespace::PolicyService]`.
85131
You might see where I'm headed ;)
@@ -97,4 +143,4 @@ And you'll get a `NameError` because (let's pretend) `::RatingService` isn't a t
97143
In the second example, the module nesting is `SomeEngine::SomeNamespace::RatingService`.
98144
As a result, `PolicyService.create_policy2` works as expected, first checking for `SomeEngine::SomeNamespace::RatingService` then `SomeEngine::RatingService` and finally `::RatingService`.
99145

100-
Rails 6 reworks how autoloading is done using a library called Zeitwerk and I'm really excited for it! (https://github.com/fxn/zeitwerk)
146+
Rails 6 reworks (thankfully :sweat_smile:) how autoloading is done using a library called [Zeitwerk](https://github.com/fxn/zeitwerk) and I'm really excited for it!

_site/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ <h2>
6969
</a>
7070
</li>
7171
<li>
72+
<span class="post-meta mono">2020-01-23</span>
73+
<a href="/2020/01/23/farewell-rails-autoloading.html">
74+
Classic Rails Autoloading - Eigenclasses
75+
</a>
76+
</li>
77+
<li>
7278
<span class="post-meta mono">2012-11-23</span>
7379
<a href="/2012/11/23/the-oh-so-useful-script-command.html">
7480
The oh-so useful script command

0 commit comments

Comments
 (0)