From c9593fc77f31f72bde56e2d370c6aee99fe3e46d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 15 Feb 2016 14:25:10 -0800 Subject: fix recursive templates --- actionview/lib/action_view/digestor.rb | 60 ++++++++++++++++++++----------- actionview/test/template/digestor_test.rb | 5 +-- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb index cda380c78d..5a07cec773 100644 --- a/actionview/lib/action_view/digestor.rb +++ b/actionview/lib/action_view/digestor.rb @@ -55,25 +55,30 @@ module ActionView end end - def self.tree(name, finder, partial = false, seen = {}) - if obj = seen[name] - obj - else - logical_name = name.gsub(%r|/_|, "/") + def self.tree(name, finder, injected = [], partial = false, seen = {}) + logical_name = name.gsub(%r|/_|, "/") + partial = partial || name.include?("/_") + + if finder.disable_cache { finder.exists?(logical_name, [], partial) } + template = finder.disable_cache { finder.find(logical_name, [], partial) } - if finder.disable_cache { finder.exists?(logical_name, [], partial) } - template = finder.disable_cache { finder.find(logical_name, [], partial) } - node = seen[name] = Node.new(name, logical_name, template, partial, []) + if obj = seen[template.identifier] + obj else - node = seen[name] = Missing.new(name, logical_name, nil, partial, []) - return node - end + klass = partial ? Partial : Node + node = seen[template.identifier] = klass.new(name, logical_name, template, partial, []) - deps = DependencyTracker.find_dependencies(name, template, finder.view_paths) - deps.each do |dep_file| - node.children << tree(dep_file, finder, true, seen) + deps = DependencyTracker.find_dependencies(name, template, finder.view_paths) + deps.each do |dep_file| + node.children << tree(dep_file, finder, [], true, seen) + end + injected.each do |template| + node.children << Injected.new(template, nil, nil, partial, []) + end + node end - node + else + seen[name] = Missing.new(name, logical_name, nil, partial, []) end end @@ -86,21 +91,36 @@ module ActionView end end - def digest - Digest::MD5.hexdigest("#{template.source}-#{dependency_digest}") + def digest stack = [] + Digest::MD5.hexdigest("#{template.source}-#{dependency_digest(stack)}") end - def dependency_digest - children.map(&:digest).join("-") + def dependency_digest(stack) + children.map do |node| + if stack.include?(node) + false + else + stack.push node + node.digest(stack).tap { stack.pop } + end + end.join("-") end end + class Partial < Node; end + class Missing < Node - def digest + def digest(_ = []) '' end end + class Injected < Node + def digest(_ = []) + name + end + end + attr_reader :name, :finder, :options def initialize(name, finder, options = {}) diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb index 6ce06e8073..d2d4aec348 100644 --- a/actionview/test/template/digestor_test.rb +++ b/actionview/test/template/digestor_test.rb @@ -311,9 +311,10 @@ class TemplateDigestorTest < ActionView::TestCase finder.variants = options.delete(:variants) || [] - node = ActionView::Digestor.tree template_name, finder + node = ActionView::Digestor.tree(template_name, finder, options[:dependencies] || []) + y = node.digest x = ActionView::Digestor.digest({ name: template_name, finder: finder }.merge(options)) - assert_equal x, node.digest + assert_equal x, y x end -- cgit v1.2.3