1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 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 72 73
|
class Jbuilder::DependencyTracker
EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
# Matches:
# json.partial! "messages/message"
# json.partial!('messages/message')
#
DIRECT_RENDERS = /
\w+\.partial! # json.partial!
\(?\s* # optional parenthesis
(['"])([^'"]+)\1 # quoted value
/x
# Matches:
# json.partial! partial: "comments/comment"
# json.comments @post.comments, partial: "comments/comment", as: :comment
# json.array! @posts, partial: "posts/post", as: :post
# = render partial: "account"
#
INDIRECT_RENDERS = /
(?::partial\s*=>|partial:) # partial: or :partial =>
\s* # optional whitespace
(['"])([^'"]+)\1 # quoted value
/x
def self.call(name, template, view_paths = nil)
new(name, template, view_paths).dependencies
end
def initialize(name, template, view_paths = nil)
@name, @template, @view_paths = name, template, view_paths
end
def dependencies
direct_dependencies + indirect_dependencies + explicit_dependencies
end
private
attr_reader :name, :template
def direct_dependencies
source.scan(DIRECT_RENDERS).map(&:second)
end
def indirect_dependencies
source.scan(INDIRECT_RENDERS).map(&:second)
end
def explicit_dependencies
dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("/*") }
(explicits + resolve_directories(wildcards)).uniq
end
def resolve_directories(wildcard_dependencies)
return [] unless @view_paths
return [] if wildcard_dependencies.empty?
# Remove trailing "/*"
prefixes = wildcard_dependencies.map { |query| query[0..-3] }
@view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
path.to_s if prefixes.include?(path.prefix)
}.sort
end
def source
template.source
end
end
|