Thursday, August 17, 2017

Rails 5: Autoloading and Reloading Constants



Rails 5 disables autoloading after booting the app in production. With Rails 5, autoloading is now completely disabled if config.eager_load = true.

The concept of loading all the constants even before they are actually needed is called “Eager loading”. In a way it is opposite of “Autoloading”. In the case of “Autoloading” the application does not load the constant until it is needed. Once a class is needed and it is missing then the application starts looking in “autoloading paths” to load the missing class.

When application boots in production then the application loads all constants found in all directories listed in eager_load_paths. If folder in the autoload_paths but not in the eager_load_paths are not going to be loaded in production. What this means is that if file paths outside of app/ are in your config.autoload_paths and not in config.eager_load_paths (for example, lib/), these files will no longer load in deployed environments.


In my case I had a file called calendar.rb in the lib folder.

class Calendar < Struct.new(:view, :date, :callback)
...
end


and I was trying to use this class in a helper:


module CalendarHelper

  include ActionView::Helpers::OutputSafetyHelper

  include ActionView::Helpers::TagHelper

  include ActionView::Context
  def calendar(date = Date.current, &block)
    Calendar.new(self, date,  block).display
  end

...
end 


In my application.rb I had next configuration:

config.autoload_paths += %W(#{config.root}/lib)

But when I was trying to call Calendar.new from my helper, I was getting an error. Strange errors regarding missing requires and dependencies.


ActionView::Template::Error (uninitialized constant CalendarHelper::Calendar):

So what I had to do was change the configuration

# config/application.rb
config.eager_load_paths << Rails.root.join('lib')

And now everything works fine


No comments:

Post a Comment