Class: Mona::Loaders::Zeitwerk

Inherits:
Base
  • Object
show all
Includes:
Mixins
Defined in:
lib/mona/loaders/zeitwerk.rb

Constant Summary collapse

ERROR_MESSAGE_REGEX =
/expected file (?<path>[\w\/]+.rb) to define constant (?<klass>[\w:]+)/

Instance Method Summary collapse

Methods included from Mixins

included

Constructor Details

#initializeZeitwerk

Returns a new instance of Zeitwerk.



9
10
11
12
13
14
# File 'lib/mona/loaders/zeitwerk.rb', line 9

def initialize(...)
  @loader = Zeitwerk::Loader.new
  @loader.inflector = Class.new(Zeitwerk::Inflector).new

  super(...)
end

Instance Method Details

#apply_rules_for(entity) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/mona/loaders/zeitwerk.rb', line 54

def apply_rules_for(entity)
  @autoload_dirs.uniq.each { entity.push_dir(_1) }
  @ignore_dirs.uniq
    .map { File.join(Mona.current_project.root_path, _1) }
    .each { entity.ignore( _1 ) }

  entity.inflector.inflect(@inflections)

  result_overwriter = ->(kname) { @overwriters.each { |o| kname = o.call(kname) }; kname }
  entity.inflector.define_singleton_method(:camelize) do |basename, abspath|
    result_overwriter.call( super(basename, abspath) )
  end
end

#check_classesObject

Raises:

  • (StandardError)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/mona/loaders/zeitwerk.rb', line 29

def check_classes
  check_classes_loader = @loader.dup
  check_classes_loader.on_load { |cpath, value, abspath| puts value }

  errors = []

  begin
    check_classes_loader.eager_load
  rescue Zeitwerk::NameError => e
    match = e.message.match(ERROR_MESSAGE_REGEX)

    raise e if match.nil?

    # TODO: use logger
    errors << "#{match[:path]} => #{match[:klass]}"
    check_classes_loader.ignore(match[:path])
    retry
  end

  puts errors
  raise StandardError.new("loader fails with #{errors.count} errors") if errors.any?

  nil
end

#eager_loadObject



21
22
23
24
25
26
27
# File 'lib/mona/loaders/zeitwerk.rb', line 21

def eager_load
  time = Benchmark.realtime do
    @loader.eager_load
  end

  puts "eager_load dependencies in #{'%.2f' % time} seconds"
end

#ignore(glob) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/mona/loaders/zeitwerk.rb', line 68

def ignore(glob)
  super(glob)

  # TODO: if loader.setup is true => push dir directly to the @loader
  @ignore_dirs
    .uniq
    .map { File.join(root_path, _1) }
    .each { @loader.ignore( _1 ) }
end

#setupObject



16
17
18
19
# File 'lib/mona/loaders/zeitwerk.rb', line 16

def setup
  apply_rules_for(@loader)
  @loader.setup
end