Skip to content

Commit aa6a95a

Browse files
committed
Lazily boot the rails app during tapioca gem
1 parent cc54939 commit aa6a95a

File tree

1 file changed

+1
-113
lines changed

1 file changed

+1
-113
lines changed

lib/tapioca/loaders/loader.rb

Lines changed: 1 addition & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@ def load; end
2929
def load_bundle(gemfile, initialize_file, require_file, halt_upon_load_error)
3030
require_helper(initialize_file)
3131

32-
load_rails_application(halt_upon_load_error: halt_upon_load_error)
32+
load_rails_application(environment_load: true, halt_upon_load_error: halt_upon_load_error)
3333

3434
gemfile.require_bundle
3535

3636
require_helper(require_file)
37-
38-
load_rails_engines
3937
end
4038

4139
sig do
@@ -85,116 +83,6 @@ def load_rails_application(environment_load: false, eager_load: false, app_root:
8583
say("Continuing RBI generation without loading the Rails application.")
8684
end
8785

88-
sig { void }
89-
def load_rails_engines
90-
return if engines.empty?
91-
92-
with_rails_application do
93-
run_initializers
94-
95-
if zeitwerk_mode?
96-
load_engines_in_zeitwerk_mode
97-
else
98-
load_engines_in_classic_mode
99-
end
100-
end
101-
end
102-
103-
def run_initializers
104-
engines.each do |engine|
105-
engine.instance.initializers.tsort_each do |initializer|
106-
initializer.run(Rails.application)
107-
rescue ScriptError, StandardError
108-
nil
109-
end
110-
end
111-
end
112-
113-
sig { void }
114-
def load_engines_in_zeitwerk_mode
115-
# Collect all the directories that are already managed by all existing Zeitwerk loaders.
116-
managed_dirs = Zeitwerk::Registry.loaders.flat_map(&:dirs).to_set
117-
# We use a fresh loader to load the engine directories, so that we don't interfere with
118-
# any of the existing loaders.
119-
autoloader = Zeitwerk::Loader.new
120-
121-
engines.each do |engine|
122-
eager_load_paths(engine).each do |path|
123-
# Zeitwerk only accepts existing directories in `push_dir`.
124-
next unless File.directory?(path)
125-
# We should not add directories that are already managed by a Zeitwerk loader.
126-
next if managed_dirs.member?(path)
127-
128-
autoloader.push_dir(path)
129-
end
130-
end
131-
132-
autoloader.setup
133-
end
134-
135-
sig { void }
136-
def load_engines_in_classic_mode
137-
# This is code adapted from `Rails::Engine#eager_load!` in
138-
# https://github.com/rails/rails/blob/d9e188dbab81b412f73dfb7763318d52f360af49/railties/lib/rails/engine.rb#L489-L495
139-
#
140-
# We can't use `Rails::Engine#eager_load!` directly because it will raise as soon as it encounters
141-
# an error, which is not what we want. We want to try to load as much as we can.
142-
engines.each do |engine|
143-
eager_load_paths(engine).each do |load_path|
144-
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
145-
require_dependency file
146-
end
147-
rescue ScriptError, StandardError
148-
nil
149-
end
150-
end
151-
end
152-
153-
sig { returns(T::Boolean) }
154-
def zeitwerk_mode?
155-
Rails.respond_to?(:autoloaders) &&
156-
Rails.autoloaders.respond_to?(:zeitwerk_enabled?) &&
157-
Rails.autoloaders.zeitwerk_enabled?
158-
end
159-
160-
sig { params(blk: T.proc.void).void }
161-
def with_rails_application(&blk)
162-
# Store the current Rails.application object so that we can restore it
163-
rails_application = T.unsafe(Rails.application)
164-
165-
# Create a new Rails::Application object, so that we can load the engines.
166-
# Some engines and the `Rails.autoloaders` call might expect `Rails.application`
167-
# to be set, so we need to create one here.
168-
unless rails_application
169-
Rails.application = Class.new(Rails::Application)
170-
end
171-
172-
blk.call
173-
ensure
174-
Rails.app_class = Rails.application = rails_application
175-
end
176-
177-
T::Sig::WithoutRuntime.sig { returns(T::Array[T.class_of(Rails::Engine)]) }
178-
def engines
179-
return [] unless defined?(Rails::Engine)
180-
181-
safe_require("active_support/core_ext/class/subclasses")
182-
183-
project_path = Bundler.default_gemfile.parent.expand_path
184-
# We can use `Class#descendants` here, since we know Rails is loaded
185-
Rails::Engine
186-
.descendants
187-
.reject(&:abstract_railtie?)
188-
.reject { |engine| gem_in_app_dir?(project_path, engine.config.root.to_path) }
189-
end
190-
191-
sig { params(path: String).void }
192-
def safe_require(path)
193-
require path
194-
rescue LoadError
195-
nil
196-
end
197-
19886
sig { void }
19987
def eager_load_rails_app
20088
application = Rails.application

0 commit comments

Comments
 (0)