diff options
Diffstat (limited to 'actionview/lib/action_view/template')
-rw-r--r-- | actionview/lib/action_view/template/error.rb | 8 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers.rb | 4 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/erb.rb | 25 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/html.rb | 9 | ||||
-rw-r--r-- | actionview/lib/action_view/template/handlers/raw.rb | 4 | ||||
-rw-r--r-- | actionview/lib/action_view/template/resolver.rb | 62 | ||||
-rw-r--r-- | actionview/lib/action_view/template/types.rb | 30 |
7 files changed, 87 insertions, 55 deletions
diff --git a/actionview/lib/action_view/template/error.rb b/actionview/lib/action_view/template/error.rb index b03b197cb5..3f38c3d2b9 100644 --- a/actionview/lib/action_view/template/error.rb +++ b/actionview/lib/action_view/template/error.rb @@ -59,6 +59,9 @@ module ActionView class Error < ActionViewError #:nodoc: SOURCE_CODE_RADIUS = 3 + # Override to prevent #cause resetting during re-raise. + attr_reader :cause + def initialize(template, original_exception = nil) if original_exception ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \ @@ -67,6 +70,7 @@ module ActionView super($!.message) set_backtrace($!.backtrace) + @cause = $! @template, @sub_templates = template, nil end @@ -131,13 +135,13 @@ module ActionView end def formatted_code_for(source_code, line_counter, indent, output) - start_value = (output == :html) ? {} : "" + start_value = (output == :html) ? {} : [] source_code.inject(start_value) do |result, line| line_counter += 1 if output == :html result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line]) else - result << "%#{indent}s: %s\n" % [line_counter, line] + result << "%#{indent}s: %s" % [line_counter, line] end end end diff --git a/actionview/lib/action_view/template/handlers.rb b/actionview/lib/action_view/template/handlers.rb index 0105e88a49..ad4c353608 100644 --- a/actionview/lib/action_view/template/handlers.rb +++ b/actionview/lib/action_view/template/handlers.rb @@ -2,13 +2,15 @@ module ActionView #:nodoc: # = Action View Template Handlers class Template module Handlers #:nodoc: + autoload :Raw, 'action_view/template/handlers/raw' autoload :ERB, 'action_view/template/handlers/erb' + autoload :Html, 'action_view/template/handlers/html' autoload :Builder, 'action_view/template/handlers/builder' - autoload :Raw, 'action_view/template/handlers/raw' def self.extended(base) base.register_default_template_handler :raw, Raw.new base.register_template_handler :erb, ERB.new + base.register_template_handler :html, Html.new base.register_template_handler :builder, Builder.new base.register_template_handler :ruby, :source.to_proc end diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb index 1f8459c24b..85a100ed4c 100644 --- a/actionview/lib/action_view/template/handlers/erb.rb +++ b/actionview/lib/action_view/template/handlers/erb.rb @@ -123,31 +123,6 @@ 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/html.rb b/actionview/lib/action_view/template/handlers/html.rb new file mode 100644 index 0000000000..ccaa8d1469 --- /dev/null +++ b/actionview/lib/action_view/template/handlers/html.rb @@ -0,0 +1,9 @@ +module ActionView + module Template::Handlers + class Html < Raw + def call(template) + "ActionView::OutputBuffer.new #{super}" + end + end + end +end diff --git a/actionview/lib/action_view/template/handlers/raw.rb b/actionview/lib/action_view/template/handlers/raw.rb index b08fb0870f..760f517431 100644 --- a/actionview/lib/action_view/template/handlers/raw.rb +++ b/actionview/lib/action_view/template/handlers/raw.rb @@ -2,9 +2,7 @@ module ActionView module Template::Handlers class Raw def call(template) - escaped = template.source.gsub(':'.freeze, '\:'.freeze) - - '%q:' + escaped + ':;' + "#{template.source.inspect};" end end end diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb index 7859c58b43..bf68e93c58 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 "concurrent" +require "concurrent/map" module ActionView # = Action View Resolver @@ -55,6 +55,10 @@ module ActionView @query_cache = SmallCache.new end + def inspect + "#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>" + end + # Cache the templates returned by the block def cache(key, name, prefix, partial, locals) if Resolver.caching? @@ -84,6 +88,23 @@ module ActionView @query_cache.clear end + # Get the cache size. Do not call this + # method. This method is not guaranteed to be here ever. + def size # :nodoc: + size = 0 + @data.each_value do |v1| + v1.each_value do |v2| + v2.each_value do |v3| + v3.each_value do |v4| + size += v4.size + end + end + end + end + + size + @query_cache.size + end + private def canonical_no_templates(templates) @@ -126,6 +147,12 @@ module ActionView end end + def find_all_anywhere(name, prefix, partial=false, details={}, key=nil, locals=[]) + cached(key, [name, prefix, partial], details, locals) do + find_templates(name, prefix, partial, details, true) + end + end + def find_all_with_query(query) # :nodoc: @cache.cache_query(query) { find_template_paths(File.join(@path, query)) } end @@ -187,15 +214,16 @@ module ActionView private - def find_templates(name, prefix, partial, details) + def find_templates(name, prefix, partial, details, outside_app_allowed = false) path = Path.build(name, prefix, partial) - query(path, details, details[:formats]) + query(path, details, details[:formats], outside_app_allowed) end - def query(path, details, formats) + def query(path, details, formats, outside_app_allowed) query = build_query(path, details) template_paths = find_template_paths(query) + template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed template_paths.map do |template| handler, format, variant = extract_handler_and_format_and_variant(template, formats) @@ -210,14 +238,24 @@ module ActionView end end + def reject_files_external_to_app(files) + files.reject { |filename| !inside_path?(@path, filename) } + end + def find_template_paths(query) - Dir[query].reject do |filename| + Dir[query].uniq.reject do |filename| File.directory?(filename) || # deals with case-insensitive file systems. !File.fnmatch(query, filename, File::FNM_EXTGLOB) end end + def inside_path?(path, filename) + filename = File.expand_path(filename) + path = File.join(path, '') + filename.start_with?(path) + end + # Helper for building query glob string based on resolver's pattern. def build_query(path, details) query = @pattern.dup @@ -228,8 +266,12 @@ module ActionView partial = escape_entry(path.partial? ? "_#{path.name}" : path.name) query.gsub!(/:action/, partial) - details.each do |ext, variants| - query.gsub!(/:#{ext}/, "{#{variants.compact.uniq.join(',')}}") + details.each do |ext, candidates| + if ext == :variants && candidates == :any + query.gsub!(/:#{ext}/, "*") + else + query.gsub!(/:#{ext}/, "{#{candidates.compact.uniq.join(',')}}") + end end File.expand_path(query, @path) @@ -323,7 +365,11 @@ module ActionView query = escape_entry(File.join(@path, path)) exts = EXTENSIONS.map do |ext, prefix| - "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}" + if ext == :variants && details[ext] == :any + "{#{prefix}*,}" + else + "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}" + end end.join query + exts diff --git a/actionview/lib/action_view/template/types.rb b/actionview/lib/action_view/template/types.rb index be45fcf742..b32567cd66 100644 --- a/actionview/lib/action_view/template/types.rb +++ b/actionview/lib/action_view/template/types.rb @@ -1,23 +1,15 @@ -require 'set' require 'active_support/core_ext/module/attribute_accessors' module ActionView class Template class Types class Type - cattr_accessor :types - self.types = Set.new - - def self.register(*t) - types.merge(t.map(&:to_s)) - end - - register :html, :text, :js, :css, :xml, :json + SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ]) def self.[](type) - return type if type.is_a?(self) - - if type.is_a?(Symbol) || types.member?(type.to_s) + if type.is_a?(self) + type + else new(type) end end @@ -28,16 +20,18 @@ module ActionView @symbol = symbol.to_sym end - delegate :to_s, :to_sym, :to => :symbol + def to_s + @symbol.to_s + end alias to_str to_s def ref - to_sym || to_s + @symbol end + alias to_sym ref def ==(type) - return false if type.blank? - symbol.to_sym == type.to_sym + @symbol == type.to_sym unless type.blank? end end @@ -52,6 +46,10 @@ module ActionView def self.[](type) type_klass[type] end + + def self.symbols + type_klass::SET.symbols + end end end end |