Skip to content

Commit 336ca2e

Browse files
committed
fix: lazy loading
This fix initializes lazy loading or eager loading after the first time a generator is called, which can be a bit surprising. But this guarantees that the `Faker::Config.lazy_loading` setting is respected.
1 parent 6171010 commit 336ca2e

1 file changed

Lines changed: 49 additions & 33 deletions

File tree

lib/faker.rb

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -288,46 +288,62 @@ def disable_enforce_available_locales
288288
end
289289
end
290290

291-
if Faker::Config.lazy_loading?
292-
def self.load_path(*constants)
293-
constants.map do |class_name|
294-
class_name
295-
.to_s
296-
.gsub('::', '/')
297-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
298-
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
299-
.tr('-', '_')
300-
.downcase
301-
end.join('/')
291+
def self.load_path(*constants)
292+
constants.map do |class_name|
293+
class_name
294+
.to_s
295+
.gsub('::', '/')
296+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
297+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
298+
.tr('-', '_')
299+
.downcase
300+
end.join('/')
301+
end
302+
303+
# TODO: refactor this
304+
305+
def self.resolve_const(context_name, class_name)
306+
load_path = case class_name
307+
when :DnD
308+
load_path('faker/games/dnd')
309+
else
310+
load_path(context_name, class_name)
311+
end
312+
313+
begin
314+
require(load_path)
315+
rescue LoadError
316+
require(load_path.gsub('faker/', 'faker/default/'))
302317
end
318+
end
303319

304-
def self.lazy_load(klass)
305-
def klass.const_missing(class_name)
306-
load_path = case class_name
307-
when :DnD
308-
Faker.load_path('faker/games/dnd')
309-
else
310-
Faker.load_path(name, class_name)
311-
end
312-
313-
begin
314-
require(load_path)
315-
rescue LoadError
316-
require(load_path.gsub('faker/', 'faker/default/'))
317-
end
320+
private_class_method :resolve_const
318321

319-
const_get(class_name)
322+
EAGER_LOAD_MUTEX = Mutex.new
323+
private_constant :EAGER_LOAD_MUTEX
324+
325+
# initial usage determines lazy loading or eager loading
326+
# TODO: this can be a bit surprising and error-prone
327+
def self.const_missing(class_name)
328+
EAGER_LOAD_MUTEX.synchronize do
329+
if Config.lazy_loading?
330+
resolve_const(name, class_name)
331+
elsif !@eager_load
332+
@eager_load = true
333+
Dir.glob(["#{__dir__}/faker/*.rb", "#{__dir__}/faker/**/*.rb"]).each { |f| require f }
320334
end
321335
end
322336

323-
lazy_load(self)
337+
const_get(class_name)
324338
end
325-
end
326339

327-
unless Faker::Config.lazy_loading?
328-
rb_files = []
329-
rb_files << File.join(mydir, 'faker', '*.rb')
330-
rb_files << File.join(mydir, 'faker', '/**/*.rb')
340+
def self.lazy_load(klass)
341+
mutex = Mutex.new
342+
343+
klass.define_singleton_method(:const_missing) do |class_name|
344+
mutex.synchronize { Faker.resolve_const(name, class_name) }
331345

332-
Dir.glob(rb_files).each { |file| require file }
346+
const_get(class_name)
347+
end
348+
end
333349
end

0 commit comments

Comments
 (0)