Class: Flickwerk::PatchFinder

Inherits:
Object
  • Object
show all
Defined in:
lib/flickwerk/patch_finder.rb

Constant Summary collapse

DECORATED_CLASS_PATTERN =
/(?:::)?(?<decorated_class>[A-Z][\w.:]+?)(?:\.singleton_class)?\.prepend[\s(]/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, autoloader: Rails.autoloaders.main) ⇒ PatchFinder

Returns a new instance of PatchFinder.



9
10
11
12
# File 'lib/flickwerk/patch_finder.rb', line 9

def initialize(path, autoloader: Rails.autoloaders.main)
  @autoloader = autoloader
  @path = path
end

Instance Attribute Details

#autoloaderObject (readonly)

Returns the value of attribute autoloader.



7
8
9
# File 'lib/flickwerk/patch_finder.rb', line 7

def autoloader
  @autoloader
end

#pathObject (readonly)

Returns the value of attribute path.



7
8
9
# File 'lib/flickwerk/patch_finder.rb', line 7

def path
  @path
end

Instance Method Details

#callObject



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/flickwerk/patch_finder.rb', line 14

def call
  path.glob("**/*_patch.rb") do |patch_path|
    # Match all the classes that are prepended in the file
    matches = File.read(patch_path).scan(DECORATED_CLASS_PATTERN).flatten

    # Don't do a thing if there's no prepending.
    raise Flickwerk::Error, "No classes prepended in #{patch_path}" if matches.empty?

    # For each unique match, make sure we load the decorator when the base class is loaded
    matches.uniq.each do |decorated_class|
      # Zeitwerk tells us which constant it expects a file to provide.
      decorator_constant = autoloader.cpath_expected_at(patch_path)
      Flickwerk.patch(decorated_class, with: decorator_constant)
    end
  end
end