Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Anatomy of constant lookup and autoloading in R...
Search
Prathamesh Sonpatki
March 19, 2016
1
190
Anatomy of constant lookup and autoloading in Rails
Prathamesh Sonpatki
March 19, 2016
Tweet
Share
More Decks by Prathamesh Sonpatki
See All by Prathamesh Sonpatki
Secrets to Monitor Kubernetes Workloads
prathamesh
1
84
The Complete Handbook to OpenTelemetry Metrics
prathamesh
1
64
Breaking down the Pillars of Observability: From data to outcomes
prathamesh
0
54
Monitoring vs. Debugging
prathamesh
0
120
Handling High Cardinality in Observability
prathamesh
1
82
Setting up Monitoring for Kubernetes
prathamesh
0
290
Monitoring vs. Debugging - SRE BLR Meetup
prathamesh
0
81
Monitoring vs. Debugging - IG Meetup 22nd July
prathamesh
2
97
Pune_User_Group.pdf
prathamesh
0
91
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
790
Testing 201, or: Great Expectations
jmmastey
42
7.5k
Done Done
chrislema
184
16k
The Cult of Friendly URLs
andyhume
79
6.5k
It's Worth the Effort
3n
185
28k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
5
210
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
Transcript
Anatomy of constant lookup & autoloading in Rails @_cha1tanya @BigBinary
class PostsController < ApplicationController def index @posts = Post.all end
end
class PostsController < ApplicationController def index @posts = Post.all end
end
It just works! ™
Constants in Ruby
class User < ActiveRecord::Base BASE_URL = “http://example.com” end
class User < ActiveRecord::Base end
User = Class.new(ActiveRecord::Base)
module Admin class Users < ActiveRecord::Base end end
All class & module definitions create constants
class PostsController < ApplicationController def index @posts = Post.all end
end
We refer to constants while using classes or modules
Admin::ApiService::BASE_URL
Constants are stored in modules
API for handling constants
Module.const_set Module.const_get Module.const_missing Module.remove_const
Constant lookup in Ruby
class ApiController BASE_URL = “https://github.com/api/v1” def print_location puts BASE_URL #=>
? end end
Look for the constant inside current scope
class ApiController BASE_URL = “https://github.com/api/v1” def print_location puts BASE_URL” end
end #=> “https://github.com/api/v1
module Admin BASE_URL = “https://github.com/api/v1” class ApiController def print_location puts
BASE_URL #=> ? end end end
Look for the constant in the parent namespace
module Admin BASE_URL = “https://github.com/api/v1” class ApiController def print_location puts
BASE_URL end end end #=> “https://github.com/api/v1”
module SuperAdmin BASE_URL = “https://github.com/api/v1” module Admin class ApiController <
BaseController def print_location puts BASE_URL #=> ? end end end end
Keep looking in the parent namespaces
module SuperAdmin BASE_URL = “https://github.com/api/v1” module Admin class ApiController <
BaseController def print_location puts BASE_URL end end end end #=> “https://github.com/api/v1”
class BaseController BASE_URL = “https://github.com/api/v1” end class ApiController < BaseController
def print_location puts BASE_URL #=> ? end end
class BaseController BASE_URL = “https://github.com/api/v1” end class ApiController < BaseController
def print_location puts BASE_URL end end #=> “https://github.com/api/v1”
Look for the constant in the ancestors chain
class BaseController BASE_URL = “https://github.com/api/v2” end module Admin BASE_URL =
“https://github.com/api/v1” class ApiController < BaseController def print_location puts BASE_URL #=> ? end end end
module Admin BASE_URL = “https://github.com/api/v1” class ApiController < BaseController def
print_location puts BASE_URL end end end #=> “https://github.com/api/v1”
class BaseController BASE_URL = “https://github.com/api/v2” end module Admin class ApiController
< BaseController def print_location puts BASE_URL end end end #=> “https://github.com/api/v2”
Search in namespaces
Search in namespaces Search in ancestors tree
module SuperAdmin BASE_URL = “https://github.com/api/v1” module Admin BASE_URL = “https://github.com/api/v2”
end end
module SuperAdmin class Admin::ApiController def print_location puts BASE_URL #=> ?
end end end
module SuperAdmin class Admin::ApiController def print_location puts BASE_URL #=> ?
end end end
module SuperAdmin class Admin::ApiController def print_location puts BASE_URL end end
end #=> “https://github.com/api/v1”
module SuperAdmin BASE_URL = “https://github.com/api/v1” module Admin BASE_URL = “https://github.com/api/v2”
end end
Module.nesting
module SuperAdmin class Admin::ApiController puts Module.nesting end end
[SuperAdmin::Admin::ApiController, SuperAdmin]
[SuperAdmin::Admin::ApiController, SuperAdmin]
SuperAdmin::Admin::ApiController Not Found
[SuperAdmin::Admin::ApiController, SuperAdmin]
module SuperAdmin BASE_URL = “https://github.com/api/v1” module Admin BASE_URL = “https://github.com/api/v2”
end end
SuperAdmin::Admin
SuperAdmin::Admin Not Checked!
Ruby’s constant lookup algorithm**
Search in current namespace
Continue searching up in parent namespaces**
All namespaces are exhausted
Search in ancestors chain of the innermost class/module
Ancestors chain is exhausted
Module.const_missing(const_name)
Entry point for Rails!
# activesupport/lib/../dependencies.rb def const_missing(const_name) …… end
Autoloading in Rails
Loading mechanism
require v/s load
require require’s only once!
load will load and execute every time!
require in production
require in production load in development
config.cache_classes
Autoload Paths
config.autoload_paths
app/assets app/channels app/controllers app/controllers/concerns app/helpers app/jobs app/mailers app/models app/models/concerns test/mailers/previews
Similar to $LOAD_PATH in Ruby
Constant lookup by Rails
class PostsController < ApplicationController def index @posts = Post.all end
end
PostsController ApplicationController Post
PostsController
class PostsController < ApplicationController def index @posts = Post.all end
end
Constants after class or module
No autoloading by Rails
ApplicationController
class PostsController < ApplicationController def index @posts = Post.all end
end
Top level constant
app/assets/application_controller.rb
app/assets/application_controller.rb app/channels/application_controller.rb
app/assets/application_controller.rb app/channels/application_controller.rb app/controllers/application_controller.rb # FOUND!
Post
class PostsController < ApplicationController def index @posts = Post.all end
end
PostsController::Post
Namespaced constants
app/assets/posts_controller/post.rb app/channels/posts_controller/post.rb app/controllers/posts_controller/post.rb …
app/assets/posts_controller/post app/channels/posts_controller/post app/controllers/posts_controller/post …
Automatic modules
module Admin end module Admin class User < ActiveRecord::Base end
Admin::User
Module acting as namespace
app/models/admin
app/models/admin app/models/admin/user.rb
Admin = Module.new
Coming back to Post
app/assets/posts_controller/post app/channels/posts_controller/post app/controllers/posts_controller/post …
PostsController::Post # Not Found
Search for Post constant
app/assets/post.rb app/channels/post.rb app/controllers/post.rb … app/models/post.rb # FOUND!
Qualified constants
module Admin class User < ActiveRecord::Base end end Admin::User #
Qualified constant
class User < ActiveRecord::Base end User # Top level constant
Admin::User
admin/user.rb
admin/user.rb
user.rb
user.rb
Admin::User
Name error when not found
Constant lookup by Rails
Look for regular .rb file
Look for automatic module
Repeat search in parent namespace**
The file is found, the constant is found
File found, constant not defined
LoadError
Constant not found, File not found
NameError
Constant Reloading
config.cache_classes = false
List of monitored files
config/routes.rb Locales Ruby files under autoload paths db/schema.rb & db/structure.sql
Module.remove_const
Wipe out all autoloader constants at the start of request
@posts = Post.all
Module.const_missing again!
Reloading != Reloading
Reloading == Wiping
Convenient to wipe out & wait for autoload to kick!
What happens with Gems?
# config/application.rb Bundler.require(*Rails.groups)
Gems are already require’d
Unless require: false
Gotchas
Side effects of assumptions by Rails
Nesting information is not passed
module Admin class User < ActiveRecord::Base end end
class User < ActiveRecord::Base end
class Admin::UsersController def index @users = User.all end end
Admin::User or User?
class Admin::UsersController def index @users = User.all end end #
app/models/user.rb # In Ruby
class Admin::UsersController Module.nesting #=> [Admin::UsersController] end # app/models/user.rb # In
Ruby
class Admin::UsersController def index @users = User.all end end #
app/models/admin/user.rb # In Rails
module Admin class UsersController def index @users = User.all end
end
Prefer relative constants
class Admin::UsersController def index @users = Admin::User.all end end #
app/models/admin/user.rb
Don’t mix require and autoloading
require ‘user’ class Admin::UsersController def index @users = User.all end
end
Convention over configuration
Follow the contract and you will be happy!
Thanks! @_cha1tanya @BigBinary