In Ruby, all files need to be loaded (Kernel#load, Kernel#require, Kernel#autoload) in order to have its code run. However, in Rails, we could use autoload_paths to specify the folders and files that need to be loaded automatically.
Rails internals make extensive use of it to defer as much work as possible from the boot process. But constant autoloading in Rails is not implemented with Kernel#autoload. One of the reason Rails not using autoload Module#autoload is only capable of loading files using require, so reloading would not be possible.
The console autoloads, the test suite autoloads, and of course the application autoloads
Don’t use Kernel#require a file in autoload in another autoload file
There are some default folders of autoload_paths such as
In Development and Test env, + As default, config.cache_classes sets to false, Rails autoloads files with lazyKernel#load and only reload when there’s a change in code. In console mode, need to run reload! command to reload the code. + If config.cache_classes sets to true, Rails autoloads files with lazy Kernel#require
In Production env, config.cache_classes sets to true as default, Rails autoload with lazy Kernel#require
Rails autoloads module/class in files that loaded following the file nameString#camelize and constanceString.underscore. eg:
# 'app/controllers/home_controller.rb', # 'home_controller'.camelize is 'HomeController', then the class name would be HomeController. 'HomeController'.underscore => 'home_controller'class HomeController; end# 'app/models/platform/pock/campaign.rb' # the constance would be Platform::Pock::Campaign # 'Platform::Pock::Campaign'.underscore => 'platform/pock/campaign'# Option1: module Platform module Pock class Campaign end end end... OR ... # Option2: class Platform::Pock::Campaign end # Option2, if this is defined in Ruby, there would be an exception error because the module Platform and Platform::Pock aren't defined yet. But in Rails, when a module acts as a namespace, Rails does not require the application to define a file for it, a directory matching the namespace is enough
If there is a folder that needs to autoload, just append its path to the config.autoload_paths in the config/environments/[env].rb
Autoload Mechanism
# app/controllers/platform/posts_controller.rb module Platform class PostsController < ApplicationController def index @posts = Post.all end end end# *** ApplicationController *** # If ApplicationController isn't loaded, Rails will autoload it - At first, rails try to load it inside the namespace Platform: Platform::ApplicationController #=> app/assets/platform/application_controller.rb #=> app/controllers/platform/application_controller.rb #=> [autoload dir]/platform/application_controller.rb - If there is no ApplicationController inside the Platform namespace, Rails continue load it with no namespace #=> [autoload dir]/application_controller.rb- If the ApplicationController is not found, LoadError would be raised "unable to autoload constant ApplicationController"# *** PostsController *** # If somewhere calls to this (route), even it's not defined, Ruby will just define the controller (no exception raise)# *** Post *** - Platform::PostsController::Post #=> [autoload dir]/platform/posts_controller/post.rb - Platform::Post #=> [autoload dir]/platform/post.rb - Post #=> [autoload dir]/post.rb
EagerLoad
We both know that lazy autoload would help to speed up the time starting the server, but it’s not good for the production’s performance. Because of the fact that Rails support 2 optionseager_load, eager_load_paths to solve this problem by pre-loading all the relevant modules/classes that needed when the server starts
eager_load default set to true on production env. There are also some default folders of eager_load_paths such as
passion in finding solutions and research some things relate to technical and helpful in life. Also strongly interest in foods, travel, and gentle music :)