Rails 6: enable zeitwerk autoloader (#8766)

* More loading fixes

* Go back to OpenStruct

* Shuffle things around

* Remove obsolete patches and unneeded requires

* Disable config.add_autoload_paths_to_load_path

* Fix pre-require errors

* Config not reloader
This commit is contained in:
rhymes 2020-06-22 16:27:55 +02:00 committed by GitHub
parent b8352c5333
commit 36786cf554
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 81 additions and 101 deletions

View file

@ -1,5 +1,3 @@
require "nokogiri"
class GithubTag
class GithubReadmeTag
PARTIAL = "liquids/github_readme".freeze

View file

@ -1,5 +1,3 @@
require "uri"
class GlitchTag < LiquidTagBase
attr_accessor :uri

View file

@ -1,10 +1,3 @@
# We require all authentication modules to make sure providers
# are correctly preloaded both in development and in production and
# ready to be used when needed at runtime
Dir[Rails.root.join("app/services/authentication/**/*.rb")].each do |f|
require_dependency(f)
end
module Authentication
module Providers
# Retrieves a provider that is both available and enabled

View file

@ -1,8 +0,0 @@
# Fake Aws client is used in non-production environments to prevent actual calls to AWS lambda
module Aws
class FakeClient
def invoke(*)
OpenStruct.new(payload: [{ body: { message: 0 }.to_json }.to_json])
end
end
end

View file

@ -22,22 +22,25 @@ module PracticalDeveloper
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1 # NOTE: [Rails 6] we should at least work towards updating this to 5.2
# [Rails 6] Zeitwerk is the new autoloader
# As we don't have `load_defaults 6.0` yet, it has to be enabled manually
# See <https://guides.rubyonrails.org/autoloading_and_reloading_constants.html>
config.autoloader = :zeitwerk
# Disable auto adding of default load paths to $LOAD_PATH
# Setting this to false saves Ruby from checking these directories when
# resolving require calls with relative paths, and saves Bootsnap work and
# RAM, since it does not need to build an index for them.
# see https://github.com/rails/rails/blob/6-0-stable/railties/CHANGELOG.md#rails-600rc2-july-22-2019
config.add_autoload_paths_to_load_path = false
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
config.autoload_paths += Dir["#{config.root}/app/labor/"]
config.autoload_paths += Dir["#{config.root}/app/decorators/"]
config.autoload_paths += Dir["#{config.root}/app/services/"]
config.autoload_paths += Dir["#{config.root}/app/presenters/"]
config.autoload_paths += Dir["#{config.root}/app/liquid_tags/"]
config.autoload_paths += Dir["#{config.root}/app/black_box/"]
config.autoload_paths += Dir["#{config.root}/app/sanitizers"]
config.autoload_paths += Dir["#{config.root}/app/facades"]
config.autoload_paths += Dir["#{config.root}/app/errors"]
config.autoload_paths += Dir["#{config.root}/app/view_objects"]
config.autoload_paths += Dir["#{config.root}/lib/"]
config.autoload_paths += Dir["#{config.root}/lib"]
config.eager_load_paths += Dir["#{config.root}/lib"]
config.active_job.queue_adapter = :sidekiq

View file

@ -3,5 +3,3 @@ require_relative "application"
# Initialize the Rails application.
Rails.application.initialize!
require "carrierwave/orm/activerecord"

View file

@ -0,0 +1,8 @@
Rails.application.config.to_prepare do
# We require all authentication modules to make sure providers
# are correctly preloaded and ready to be used at this point as the loading
# order is important
Dir[Rails.root.join("app/services/authentication/**/*.rb")].each do |f|
require_dependency(f)
end
end

View file

@ -1,9 +1,18 @@
AWS_LAMBDA = if Rails.env.production?
Aws::Lambda::Client.new(
region: ApplicationConfig["AWS_DEFAULT_REGION"],
access_key_id: ApplicationConfig["AWS_SDK_KEY"],
secret_access_key: ApplicationConfig["AWS_SDK_SECRET"],
)
else
Aws::FakeClient.new
end
Rails.application.reloader.to_prepare do
AWS_LAMBDA = if Rails.env.production?
Aws::Lambda::Client.new(
region: ApplicationConfig["AWS_DEFAULT_REGION"],
access_key_id: ApplicationConfig["AWS_SDK_KEY"],
secret_access_key: ApplicationConfig["AWS_SDK_SECRET"],
)
else
# Fake Aws::Lambda::Client
Class.new do
def invoke(*)
# rubocop:disable Performance/OpenStruct
OpenStruct.new(payload: [{ body: { message: 0 }.to_json }.to_json])
# rubocop:enable Performance/OpenStruct
end
end.new
end
end

View file

@ -1,6 +1,3 @@
require "ddtrace"
require "datadog/statsd"
Datadog.configure do |c|
c.tracer env: Rails.env
c.tracer enabled: Rails.env.production?

View file

@ -1,14 +1,13 @@
# TODO: [rhymes] [Rails 6] explicitly requiring dependencies in `classic` mode.
# Will move over to `zeitwerk` in a future PR
Dir.glob(Rails.root.join("lib/liquid/*.rb")).sort.each do |filename|
require_dependency filename
end
# Our custom Liquid tags are registered to Liquid::Template at the bottom of
# each files. Each Liquid tags will need to be loaded/required before the main
# Liquid gem is evoked, hence the need for the fix below.
Rails.application.config.to_prepare do
# Explicitly requiring lib/liquid to make sure that our patches are loaded
# before liquid tags are loaded
Dir.glob(Rails.root.join("lib/liquid/*.rb")).sort.each do |filename|
require_dependency filename
end
# Our custom Liquid tags are registered to Liquid::Template at the bottom of
# each files. Each Liquid tags will need to be loaded/required before the main
# Liquid gem is evoked, hence the need to pre-require them in order
Dir.glob(Rails.root.join("app/liquid_tags/*.rb")).sort.each do |filename|
require_dependency filename
end

View file

@ -1,4 +1,3 @@
require "pusher"
require "pusher/push_notifications"
Pusher.app_id = ApplicationConfig["PUSHER_APP_ID"]

View file

@ -1,13 +0,0 @@
# This eagerload our custom ReverseMarkdown::Converters and allows it to be autoreloaded
# in development.
#
# Because files are eagerloaded in production, this fix is only
# applicable in development (and test, when needed)
if Rails.env.development? || Rails.env.test?
Rails.application.config.to_prepare do
Dir.glob(Rails.root.join("app/lib/reverse_markdown/converters/*.rb")).sort.each do |filename|
require_dependency filename
end
end
end

View file

@ -1,22 +1,9 @@
# Monkey patch `stringify_keys` to make rack 2.1.1 compatible with Sidekiq UI Admin panel.
# Should be removed when 2.1.2 is released.
# https://github.com/rack/rack/pull/1428
module Rack
module Session
module Abstract
class SessionHash
private
def stringify_keys(other)
other.to_hash.transform_keys(&:to_s)
end
end
end
Rails.application.config.to_prepare do
Dir.glob(Rails.root.join("lib/sidekiq/*.rb")).sort.each do |filename|
require_dependency filename
end
end
require Rails.root.join("lib/sidekiq/worker_retries_exhausted_reporter")
Sidekiq.configure_server do |config|
sidekiq_url = ApplicationConfig["REDIS_SIDEKIQ_URL"] || ApplicationConfig["REDIS_URL"]
# On Heroku this configuration is overridden and Sidekiq will point at the redis

View file

@ -0,0 +1,15 @@
# Zeitwerk (Rails 6+) autoloader
# see https://guides.rubyonrails.org/autoloading_and_reloading_constants.html
# Configures default inflections for the zeitwerk autoloader
# see <https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#customizing-inflections>
Rails.autoloaders.each do |autoloader|
autoloader.inflector.inflect(
"html_rouge" => "HTMLRouge",
"url" => "URL",
)
end
# Ignoring folders that don't adhere to the new naming conventions
Rails.autoloaders.main.ignore(Rails.root.join("lib/data_update_scripts"))
Rails.autoloaders.main.ignore(Rails.root.join("lib/generators/data_update"))

View file

@ -1,8 +1,20 @@
require "rails_helper"
RSpec.describe Liquid::Raw do
RSpec.describe Liquid::Raw, type: :lib do
it "uses the correct regexp for invalid tokens" do
expected_regexp = /\A(.*)#{Liquid::TagStart}\s*(\w+)\s*#{Liquid::TagEnd}\z/om
expect(described_class::FullTokenPossiblyInvalid).to eq(expected_regexp)
end
it "does not allow non whitespace characters in between the tags" do
invalid_markdown = '<img src="x" class="before{% raw %}inside{% endraw ">%}rawafter"onerror=alert(document.domain) '
expect { Liquid::Template.parse(invalid_markdown) }.to raise_error(StandardError)
end
it "raise error message when link tag contain non article URL" do
invalid_markdown = "{% link /some-random-link/ %}"
expect { Liquid::Template.parse(invalid_markdown) }.to(
raise_error(StandardError, "This URL is not an article link: {% link /some-random-link/ %}"),
)
end
end

View file

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe Liquid::Variable do
RSpec.describe Liquid::Variable, type: :lib do
it "does not allow instantiation" do
expect { described_class.new("", nil) }.to raise_error(StandardError, /variables are disabled/)
end

View file

@ -1,15 +0,0 @@
require "rails_helper"
RSpec.describe Liquid::Raw, type: :liquid_tag do
it "does not allow non whitespace characters in between the tags" do
invalid_markdown = '<img src="x" class="before{% raw %}inside{% endraw ">%}rawafter"onerror=alert(document.domain) '
expect { Liquid::Template.parse(invalid_markdown) }.to raise_error(StandardError)
end
it "raise error message when link tag contain non article URL" do
invalid_markdown = "{% link /some-random-link/ %}"
expect { Liquid::Template.parse(invalid_markdown) }.to(
raise_error(StandardError, "This URL is not an article link: {% link /some-random-link/ %}"),
)
end
end