aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/template
diff options
context:
space:
mode:
Diffstat (limited to 'actionview/lib/action_view/template')
-rw-r--r--actionview/lib/action_view/template/handlers/erb.rb25
-rw-r--r--actionview/lib/action_view/template/handlers/raw.rb2
-rw-r--r--actionview/lib/action_view/template/resolver.rb42
3 files changed, 54 insertions, 15 deletions
diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb
index 85a100ed4c..1f8459c24b 100644
--- a/actionview/lib/action_view/template/handlers/erb.rb
+++ b/actionview/lib/action_view/template/handlers/erb.rb
@@ -123,6 +123,31 @@ module ActionView
).src
end
+ # Returns Regexp to extract a cached resource's name from a cache call at the
+ # first line of a template.
+ # The extracted cache name is captured as :resource_name.
+ #
+ # <% cache notification do %> # => notification
+ #
+ # The pattern should support templates with a beginning comment:
+ #
+ # <%# Still extractable even though there's a comment %>
+ # <% cache notification do %> # => notification
+ #
+ # But fail to extract a name if a resource association is cached.
+ #
+ # <% cache notification.event do %> # => nil
+ def resource_cache_call_pattern
+ /\A
+ (?:<%\#.*%>)* # optional initial comment
+ \s* # followed by optional spaces or newlines
+ <%\s*cache[\(\s] # followed by an ERB call to cache
+ \s* # followed by optional spaces or newlines
+ (?<resource_name>\w+) # capture the cache call argument as :resource_name
+ [\s\)] # followed by a space or close paren
+ /xm
+ end
+
private
def valid_encoding(string, encoding)
diff --git a/actionview/lib/action_view/template/handlers/raw.rb b/actionview/lib/action_view/template/handlers/raw.rb
index 397c86014a..b08fb0870f 100644
--- a/actionview/lib/action_view/template/handlers/raw.rb
+++ b/actionview/lib/action_view/template/handlers/raw.rb
@@ -2,7 +2,7 @@ module ActionView
module Template::Handlers
class Raw
def call(template)
- escaped = template.source.gsub(/:/, '\:')
+ escaped = template.source.gsub(':'.freeze, '\:'.freeze)
'%q:' + escaped + ':;'
end
diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
index bc0db330ea..7859c58b43 100644
--- a/actionview/lib/action_view/template/resolver.rb
+++ b/actionview/lib/action_view/template/resolver.rb
@@ -3,7 +3,7 @@ require "active_support/core_ext/class"
require "active_support/core_ext/module/attribute_accessors"
require "action_view/template"
require "thread"
-require "thread_safe"
+require "concurrent"
module ActionView
# = Action View Resolver
@@ -35,7 +35,7 @@ module ActionView
# Threadsafe template cache
class Cache #:nodoc:
- class SmallCache < ThreadSafe::Cache
+ class SmallCache < Concurrent::Map
def initialize(options = {})
super(options.merge(:initial_capacity => 2))
end
@@ -52,6 +52,7 @@ module ActionView
def initialize
@data = SmallCache.new(&KEY_BLOCK)
+ @query_cache = SmallCache.new
end
# Cache the templates returned by the block
@@ -70,8 +71,17 @@ module ActionView
end
end
+ def cache_query(query) # :nodoc:
+ if Resolver.caching?
+ @query_cache[query] ||= canonical_no_templates(yield)
+ else
+ yield
+ end
+ end
+
def clear
@data.clear
+ @query_cache.clear
end
private
@@ -116,6 +126,10 @@ module ActionView
end
end
+ def find_all_with_query(query) # :nodoc:
+ @cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
+ end
+
private
delegate :caching?, to: :class
@@ -181,9 +195,9 @@ module ActionView
def query(path, details, formats)
query = build_query(path, details)
- template_paths = find_template_paths query
+ template_paths = find_template_paths(query)
- template_paths.map { |template|
+ template_paths.map do |template|
handler, format, variant = extract_handler_and_format_and_variant(template, formats)
contents = File.binread(template)
@@ -193,36 +207,36 @@ module ActionView
:variant => variant,
:updated_at => mtime(template)
)
- }
+ end
end
def find_template_paths(query)
- Dir[query].reject { |filename|
+ Dir[query].reject do |filename|
File.directory?(filename) ||
# deals with case-insensitive file systems.
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
- }
+ end
end
# Helper for building query glob string based on resolver's pattern.
def build_query(path, details)
query = @pattern.dup
- prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1"
- query.gsub!(/\:prefix(\/)?/, prefix)
+ prefix = path.prefix.empty? ? '' : "#{escape_entry(path.prefix)}\\1"
+ query.gsub!(/:prefix(\/)?/, prefix)
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
- query.gsub!(/\:action/, partial)
+ query.gsub!(/:action/, partial)
details.each do |ext, variants|
- query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
+ query.gsub!(/:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
end
File.expand_path(query, @path)
end
def escape_entry(entry)
- entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
+ entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze)
end
# Returns the file mtime from the filesystem.
@@ -234,7 +248,7 @@ module ActionView
# from the path, or the handler, we should return the array of formats given
# to the resolver.
def extract_handler_and_format_and_variant(path, default_formats)
- pieces = File.basename(path).split(".")
+ pieces = File.basename(path).split('.'.freeze)
pieces.shift
extension = pieces.pop
@@ -270,7 +284,7 @@ module ActionView
#
# ActionController::Base.view_paths = FileSystemResolver.new(
# Rails.root.join("app/views"),
- # ":prefix{/:locale}/:action{.:formats,}{+:variants,}{.:handlers,}"
+ # ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
# )
#
# ==== Pattern format and variables