Class: ActionView::Digestor

Inherits:
Object show all
Defined in:
actionview/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

  • partial - Specifies whether the template is a partial


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

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


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

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

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

Create a dependency tree for template named name.


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
# File 'actionview/lib/action_view/digestor.rb', line 45

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
    logger.error "  '#{name}' file doesn't exist, so no dependencies"
    logger.error "  Couldn't find template for digesting: #{name}"
    seen[name] ||= Missing.new(name, logical_name, nil)
  end
end