aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/template/resolver.rb
diff options
context:
space:
mode:
authorWillian Gustavo Veiga <beberveiga@gmail.com>2018-10-02 12:55:36 -0300
committerWillian Gustavo Veiga <beberveiga@gmail.com>2018-10-02 12:57:37 -0300
commit2d4df1349efdf8dd2c8cc4503fd5a871b0066500 (patch)
tree9f71a297cf1bb30f1d59039997a60f97357d0782 /actionview/lib/action_view/template/resolver.rb
parent00c50c2b5966fa1d719c8a58564811c672a0e8c6 (diff)
parentcf608ee34dd833b0357ef4eefa692db33242d2aa (diff)
downloadrails-2d4df1349efdf8dd2c8cc4503fd5a871b0066500.tar.gz
rails-2d4df1349efdf8dd2c8cc4503fd5a871b0066500.tar.bz2
rails-2d4df1349efdf8dd2c8cc4503fd5a871b0066500.zip
Merge branch 'master' into feature/reselect-method
Diffstat (limited to 'actionview/lib/action_view/template/resolver.rb')
-rw-r--r--actionview/lib/action_view/template/resolver.rb72
1 files changed, 56 insertions, 16 deletions
diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
index 5a86f10973..08dd6fb510 100644
--- a/actionview/lib/action_view/template/resolver.rb
+++ b/actionview/lib/action_view/template/resolver.rb
@@ -16,7 +16,7 @@ module ActionView
alias_method :partial?, :partial
def self.build(name, prefix, partial)
- virtual = "".dup
+ virtual = +""
virtual << "#{prefix}/" unless prefix.empty?
virtual << (partial ? "_#{name}" : name)
new name, prefix, partial, virtual
@@ -221,9 +221,7 @@ module ActionView
end
def query(path, details, formats, outside_app_allowed)
- query = build_query(path, details)
-
- template_paths = find_template_paths(query)
+ template_paths = find_template_paths_from_details(path, details)
template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
template_paths.map do |template|
@@ -243,6 +241,11 @@ module ActionView
files.reject { |filename| !inside_path?(@path, filename) }
end
+ def find_template_paths_from_details(path, details)
+ query = build_query(path, details)
+ find_template_paths(query)
+ end
+
def find_template_paths(query)
Dir[query].uniq.reject do |filename|
File.directory?(filename) ||
@@ -279,7 +282,7 @@ module ActionView
end
def escape_entry(entry)
- entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze)
+ entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
end
# Returns the file mtime from the filesystem.
@@ -291,7 +294,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)
- pieces = File.basename(path).split(".".freeze)
+ pieces = File.basename(path).split(".")
pieces.shift
extension = pieces.pop
@@ -362,19 +365,56 @@ module ActionView
# An Optimized resolver for Rails' most common case.
class OptimizedFileSystemResolver < FileSystemResolver #:nodoc:
- def build_query(path, details)
- query = escape_entry(File.join(@path, path))
+ private
- exts = EXTENSIONS.map do |ext, prefix|
- if ext == :variants && details[ext] == :any
- "{#{prefix}*,}"
- else
- "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
+ def find_template_paths_from_details(path, details)
+ # Instead of checking for every possible path, as our other globs would
+ # do, scan the directory for files with the right prefix.
+ query = "#{escape_entry(File.join(@path, path))}*"
+
+ regex = build_regex(path, details)
+
+ Dir[query].uniq.reject do |filename|
+ # This regex match does double duty of finding only files which match
+ # details (instead of just matching the prefix) and also filtering for
+ # case-insensitive file systems.
+ !filename.match(regex) ||
+ File.directory?(filename)
+ end.sort_by do |filename|
+ # Because we scanned the directory, instead of checking for files
+ # one-by-one, they will be returned in an arbitrary order.
+ # We can use the matches found by the regex and sort by their index in
+ # details.
+ match = filename.match(regex)
+ EXTENSIONS.keys.reverse.map do |ext|
+ if ext == :variants && details[ext] == :any
+ match[ext].nil? ? 0 : 1
+ elsif match[ext].nil?
+ # No match should be last
+ details[ext].length
+ else
+ found = match[ext].to_sym
+ details[ext].index(found)
+ end
+ end
end
- end.join
+ end
- query + exts
- end
+ def build_regex(path, details)
+ query = escape_entry(File.join(@path, path))
+ exts = EXTENSIONS.map do |ext, prefix|
+ match =
+ if ext == :variants && details[ext] == :any
+ ".*?"
+ else
+ details[ext].compact.uniq.map { |e| Regexp.escape(e) }.join("|")
+ end
+ prefix = Regexp.escape(prefix)
+ "(#{prefix}(?<#{ext}>#{match}))?"
+ end.join
+
+ %r{\A#{query}#{exts}\z}
+ end
end
# The same as FileSystemResolver but does not allow templates to store