123456789_123456789_123456789_123456789_123456789_

Class: ActionView::FileSystemResolver

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Resolver
Instance Chain:
self, Resolver
Inherits: ActionView::Resolver
Defined in: actionview/lib/action_view/template/resolver.rb

Overview

A resolver that loads files from the filesystem.

Class Attribute Summary

Resolver - Inherited

Class Method Summary

Instance Attribute Summary

Resolver - Inherited

Instance Method Summary

Constructor Details

.new(path) ⇒ FileSystemResolver

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 99

def initialize(path)
  raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
  @unbound_templates = Concurrent::Map.new
  @path_parser = PathParser.new
  @path = File.expand_path(path)
  super()
end

Instance Attribute Details

#path (readonly)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 97

attr_reader :path

Instance Method Details

#==(resolver)

Alias for #eql?.

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 141

alias :== :eql?

#all_template_paths

This method is for internal use only.
[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 143

def all_template_paths # :nodoc:
  paths = template_glob("**/*")
  paths.map do |filename|
    filename.from(@path.size + 1).remove(/\.[^\/]*\z/)
  end.uniq.map do |filename|
    TemplatePath.parse(filename)
  end
end

#build_unbound_template(template) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 188

def build_unbound_template(template)
  parsed = @path_parser.parse(template.from(@path.size + 1))
  details = parsed.details
  source = source_for_template(template)

  UnboundTemplate.new(
    source,
    template,
    details: details,
    virtual_path: parsed.path.virtual,
  )
end

#built_templates

This method is for internal use only.
[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 152

def built_templates # :nodoc:
  @unbound_templates.values.flatten.flat_map(&:built_templates)
end

#clear_cache

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 107

def clear_cache
  @unbound_templates.clear
  @path_parser = PathParser.new
  super
end

#eager_load_templates(view = nil)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 113

def eager_load_templates(view = nil)
  template_glob("**/*").each do |file|
    unbound = build_unbound_template(file)
    (@unbound_templates[unbound.virtual_path] ||= []) << unbound
    unbound.bind_locals([]).send(:compile!, view) if view
  end
end

#eql?(resolver) ⇒ Boolean Also known as: #==

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 138

def eql?(resolver)
  self.class.equal?(resolver.class) && to_path == resolver.to_path
end

#escape_entry(entry) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 263

def escape_entry(entry)
  entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
end

#filter_and_sort_by_details(templates, requested_details) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 235

def filter_and_sort_by_details(templates, requested_details)
  filtered_templates = templates.select do |template|
    template.details.matches?(requested_details)
  end

  if filtered_templates.count > 1
    filtered_templates.sort_by! do |template|
      template.details.sort_key_for(requested_details)
    end
  end

  filtered_templates
end

#find(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 165

def find(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
  requested_details = key || TemplateDetails::Requested.new(**details)
  unbound_templates = unbound_templates_for(name, prefix, partial, !!key)

  unbound_template = find_best_by_details(unbound_templates, requested_details)
  return unless unbound_template
  unbound_template.bind_locals(locals)
end

#find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 156

def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
  requested_details = key || TemplateDetails::Requested.new(**details)
  unbound_templates = unbound_templates_for(name, prefix, partial, !!key)

  filter_and_sort_by_details(unbound_templates, requested_details).map do |unbound_template|
    unbound_template.bind_locals(locals)
  end
end

#find_best_by_details(templates, requested_details) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 218

def find_best_by_details(templates, requested_details)
  if templates.size == 1
    template = templates.first
    return template.details.matches?(requested_details) ? template : nil
  end

  best = best_rank = nil
  templates.each do |template|
    rank = template.details.rank_for(requested_details) or next
    if best_rank.nil? || (rank <=> best_rank) < 0
      best = template
      best_rank = rank
    end
  end
  best
end

#freeze

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 121

def freeze
  @path.freeze
  @path_parser.freeze
  @unbound_templates = @unbound_templates.each_pair.to_h unless @unbound_templates.is_a?(::Hash)
  @unbound_templates.each_value do |unbound_templates|
    unbound_templates.each(&:freeze)
    unbound_templates.freeze
  end
  @unbound_templates.freeze
  super
end

#source_for_template(template) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 184

def source_for_template(template)
  Template::Sources::File.new(template)
end

#template_glob(glob) (private)

Safe glob within @path

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 250

def template_glob(glob)
  query = File.join(escape_entry(@path), glob)
  path_with_slash = File.join(@path, "")

  Dir.glob(query).filter_map do |filename|
    filename = File.expand_path(filename)
    next if File.directory?(filename)
    next unless filename.start_with?(path_with_slash)

    filename
  end
end

#to_path

Alias for #to_s.

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 136

alias :to_path :to_s

#to_s Also known as: #to_path

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 133

def to_s
  @path.to_s
end

#unbound_templates_for(name, prefix, partial, cached) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 175

def unbound_templates_for(name, prefix, partial, cached)
  return @unbound_templates[TemplatePath.virtual(name, prefix, partial)] || [].freeze if frozen?
  return unbound_templates_from_path(TemplatePath.build(name, prefix, partial)) unless cached

  @unbound_templates.compute_if_absent(TemplatePath.virtual(name, prefix, partial)) do
    unbound_templates_from_path(TemplatePath.build(name, prefix, partial))
  end
end

#unbound_templates_from_path(path) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/template/resolver.rb', line 201

def unbound_templates_from_path(path)
  if path.name.include?(".")
    return []
  end

  # Instead of checking for every possible path, as our other globs would
  # do, scan the directory for files with the right prefix.
  paths = template_glob("#{escape_entry(path.to_s)}*")

  paths.map do |path|
    build_unbound_template(path)
  end.select do |template|
    # Select for exact virtual path match, including case sensitivity
    template.virtual_path == path.virtual
  end
end