Class: ActionView::Digestor

Inherits:
Object
  • Object
show all
Defined in:
lib/action_view/digestor.rb

Defined Under Namespace

Modules: PerExecutionDigestCacheExpiry Classes: Injected, Missing, Node, NullLogger, Partial

Constant Summary collapse

@@digest_mutex =
Mutex.new

Class Method Summary collapse

Class Method Details

.digest(name:, finder:, dependencies: []) ⇒ Object

Supported options:

  • name - Template name

  • finder - An instance of ActionView::LookupContext

  • dependencies - An array of dependent views



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/action_view/digestor.rb', line 21

def digest(name:, finder:, dependencies: [])
  dependencies ||= []
  cache_key = [ name, finder.rendered_format, dependencies ].flatten.compact.join(".")

  # this is a correctly done double-checked locking idiom
  # (Concurrent::Map's lookups have volatile semantics)
  finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
    finder.digest_cache.fetch(cache_key) do # re-check under lock
      partial = name.include?("/_")
      root = tree(name, finder, partial)
      dependencies.each do |injected_dep|
        root.children << Injected.new(injected_dep, nil, nil)
      end
      finder.digest_cache[cache_key] = root.digest(finder)
    end
  end
end

.loggerObject



39
40
41
# File 'lib/action_view/digestor.rb', line 39

def logger
  ActionView::Base.logger || NullLogger
end

.tree(name, finder, partial = false, seen = {}) ⇒ Object

Create a dependency tree for template named name.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/action_view/digestor.rb', line 44

def tree(name, finder, partial = false, seen = {})
  logical_name = name.gsub(%r|/_|, "/")

  options = {}
  options[:formats] = [finder.rendered_format] if finder.rendered_format

  if template = finder.disable_cache { finder.find_all(logical_name, [], partial, [], options).first }
    finder.rendered_format ||= template.formats.first

    if node = seen[template.identifier] # handle cycles in the tree
      node
    else
      node = seen[template.identifier] = Node.create(name, logical_name, template, partial)

      deps = DependencyTracker.find_dependencies(name, template, finder.view_paths)
      deps.uniq { |n| n.gsub(%r|/_|, "/") }.each do |dep_file|
        node.children << tree(dep_file, finder, true, seen)
      end
      node
    end
  else
    unless name.include?("#") # Dynamic template partial names can never be tracked
      logger.error "  Couldn't find template for digesting: #{name}"
    end

    seen[name] ||= Missing.new(name, logical_name, nil)
  end
end