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
65
The Complete Handbook to OpenTelemetry Metrics
prathamesh
1
50
Breaking down the Pillars of Observability: From data to outcomes
prathamesh
0
40
Monitoring vs. Debugging
prathamesh
0
91
Handling High Cardinality in Observability
prathamesh
1
71
Setting up Monitoring for Kubernetes
prathamesh
0
260
Monitoring vs. Debugging - SRE BLR Meetup
prathamesh
0
72
Monitoring vs. Debugging - IG Meetup 22nd July
prathamesh
2
86
Pune_User_Group.pdf
prathamesh
0
73
Featured
See All Featured
Embracing the Ebb and Flow
colly
84
4.5k
How to train your dragon (web standard)
notwaldorf
88
5.7k
Navigating Team Friction
lara
183
14k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
It's Worth the Effort
3n
183
27k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Docker and Python
trallard
40
3.1k
The Language of Interfaces
destraynor
154
24k
The Pragmatic Product Professional
lauravandoore
31
6.3k
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