diff options
| author | Chris Kowalik <chris@nu7hat.ch> | 2011-03-19 12:13:59 +0800 | 
|---|---|---|
| committer | José Valim <jose.valim@gmail.com> | 2011-03-20 07:01:46 +0800 | 
| commit | de1fe5e8a723baa095e83bb3ddca6af73b0aab5d (patch) | |
| tree | ce87fd1af3e71137fb92f9219f55fd4555dc40d6 | |
| parent | 445241d713782262134ede64a967369f803076ff (diff) | |
| download | rails-de1fe5e8a723baa095e83bb3ddca6af73b0aab5d.tar.gz rails-de1fe5e8a723baa095e83bb3ddca6af73b0aab5d.tar.bz2 rails-de1fe5e8a723baa095e83bb3ddca6af73b0aab5d.zip  | |
[action_view] added custom patterns to template resolver
6 files changed, 89 insertions, 24 deletions
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 589b2a1a76..0966970a68 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -5,6 +5,25 @@ require "action_view/template"  module ActionView    # = Action View Resolver    class Resolver + +    class Path < String +      attr_reader :name, :prefix, :partial, :virtual +      alias_method :partial?, :partial + +      def initialize(name, prefix, partial) +        @name, @prefix, @partial = name, prefix, partial +        rebuild(@name, @prefix, @partial) +      end + +      def rebuild(name, prefix, partial) +        @virtual = "" +        @virtual << "#{prefix}/" unless prefix.empty? +        @virtual << (partial ? "_#{name}" : name) + +        self.replace(@virtual) +      end +    end +      cattr_accessor :caching      self.caching = true @@ -41,10 +60,7 @@ module ActionView      # Helpers that builds a path. Useful for building virtual paths.      def build_path(name, prefix, partial) -      path = "" -      path << "#{prefix}/" unless prefix.empty? -      path << (partial ? "_#{name}" : name) -      path +      Path.new(name, prefix, partial)      end      # Handles templates caching. If a key is given and caching is on @@ -97,25 +113,24 @@ module ActionView    end    class PathResolver < Resolver -    EXTENSION_ORDER = [:locale, :formats, :handlers] +    EXTENSIONS = [:locale, :formats, :handlers] +    DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}" + +    def initialize(pattern=nil) +      @pattern = pattern || DEFAULT_PATTERN +      super() +    end      private      def find_templates(name, prefix, partial, details)        path = build_path(name, prefix, partial) -      query(path, EXTENSION_ORDER.map { |ext| details[ext] }, details[:formats]) +      extensions = Hash[EXTENSIONS.map { |ext| [ext, details[ext]] }.flatten(0)] +      query(path, extensions, details[:formats])      end      def query(path, exts, formats) -      query = File.join(@path, path) - -      query << exts.map { |ext| -        "{#{ext.compact.map { |e| ".#{e}" }.join(',')},}" -      }.join - -      query.gsub!(/\{\.html,/, "{.html,.text.html,") -      query.gsub!(/\{\.text,/, "{.text,.text.plain,") - +      query = build_query(path, exts)        templates = []        sanitizer = Hash.new { |h,k| h[k] = Dir["#{File.dirname(k)}/*"] } @@ -126,12 +141,28 @@ module ActionView          contents = File.open(p, "rb") {|io| io.read }          templates << Template.new(contents, File.expand_path(p), handler, -          :virtual_path => path, :format => format, :updated_at => mtime(p)) +          :virtual_path => path.virtual, :format => format, :updated_at => mtime(p))        end        templates      end +    # Helper for building query glob string based on resolver's pattern.  +    def build_query(path, exts) +      query = @pattern.dup +      query.gsub!(/\:prefix(\/)?/, path.prefix.empty? ? "" : "#{path.prefix}\\1") # prefix can be empty... +      query.gsub!(/\:action/, path.partial? ? "_#{path.name}" : path.name) + +      exts.each { |ext, variants| +        query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}") +      } + +      query.gsub!(/\.{html,/, ".{html,text.html,") +      query.gsub!(/\.{text,/, ".{text,text.plain,") + +      File.expand_path(query, @path) +    end +      # Returns the file mtime from the filesystem.      def mtime(p)        File.stat(p).mtime @@ -151,9 +182,9 @@ module ActionView    # A resolver that loads files from the filesystem.    class FileSystemResolver < PathResolver -    def initialize(path) +    def initialize(path, pattern=nil)        raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver) -      super() +      super(pattern)        @path = File.expand_path(path)      end diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb index 5c5cab7c7d..773dfcbb1d 100644 --- a/actionpack/lib/action_view/testing/resolvers.rb +++ b/actionpack/lib/action_view/testing/resolvers.rb @@ -8,8 +8,8 @@ module ActionView #:nodoc:    class FixtureResolver < PathResolver      attr_reader :hash -    def initialize(hash = {}) -      super() +    def initialize(hash = {}, pattern=nil) +      super(pattern)        @hash = hash      end @@ -21,8 +21,8 @@ module ActionView #:nodoc:      def query(path, exts, formats)        query = "" -      exts.each do |ext| -        query << '(' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)' +      EXTENSIONS.each do |ext| +        query << '(' << exts[ext].map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'        end        query = /^(#{Regexp.escape(path)})#{query}$/ @@ -32,9 +32,9 @@ module ActionView #:nodoc:          next unless _path =~ query          handler, format = extract_handler_and_format(_path, formats)          templates << Template.new(source, _path, handler, -          :virtual_path => $1, :format => format, :updated_at => updated_at) +          :virtual_path => path.virtual, :format => format, :updated_at => updated_at)        end - +              templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }      end    end diff --git a/actionpack/test/fixtures/custom_pattern/another.html.erb b/actionpack/test/fixtures/custom_pattern/another.html.erb new file mode 100644 index 0000000000..6d7f3bafbb --- /dev/null +++ b/actionpack/test/fixtures/custom_pattern/another.html.erb @@ -0,0 +1 @@ +Hello custom patterns!
\ No newline at end of file diff --git a/actionpack/test/fixtures/custom_pattern/html/another.erb b/actionpack/test/fixtures/custom_pattern/html/another.erb new file mode 100644 index 0000000000..dbd7e96ab6 --- /dev/null +++ b/actionpack/test/fixtures/custom_pattern/html/another.erb @@ -0,0 +1 @@ +Another template!
\ No newline at end of file diff --git a/actionpack/test/fixtures/custom_pattern/html/path.erb b/actionpack/test/fixtures/custom_pattern/html/path.erb new file mode 100644 index 0000000000..6d7f3bafbb --- /dev/null +++ b/actionpack/test/fixtures/custom_pattern/html/path.erb @@ -0,0 +1 @@ +Hello custom patterns!
\ No newline at end of file diff --git a/actionpack/test/template/resolver_patterns_test.rb b/actionpack/test/template/resolver_patterns_test.rb new file mode 100644 index 0000000000..97b1bad055 --- /dev/null +++ b/actionpack/test/template/resolver_patterns_test.rb @@ -0,0 +1,31 @@ +require 'abstract_unit' + +class ResolverPatternsTest < ActiveSupport::TestCase +  def setup +    path = File.expand_path("../../fixtures/", __FILE__) +    pattern = ":prefix/{:formats/,}:action{.:formats,}{.:handlers,}" +    @resolver = ActionView::FileSystemResolver.new(path, pattern) +  end + +  def test_should_return_empty_list_for_unknown_path +    templates = @resolver.find_all("unknown", "custom_pattern", false, {:locale => [], :formats => [:html], :handlers => [:erb]}) +    assert_equal [], templates, "expected an empty list of templates" +  end + +  def test_should_return_template_for_declared_path +    templates = @resolver.find_all("path", "custom_pattern", false, {:locale => [], :formats => [:html], :handlers => [:erb]}) +    assert_equal 1, templates.size, "expected one template" +    assert_equal "Hello custom patterns!", templates.first.source +    assert_equal "custom_pattern/path",    templates.first.virtual_path +    assert_equal [:html],                  templates.first.formats +  end + +  def test_should_return_all_templates_when_ambigous_pattern +    templates = @resolver.find_all("another", "custom_pattern", false, {:locale => [], :formats => [:html], :handlers => [:erb]}) +    assert_equal 2, templates.size, "expected two templates" +    assert_equal "Another template!",      templates[0].source +    assert_equal "custom_pattern/another", templates[0].virtual_path +    assert_equal "Hello custom patterns!", templates[1].source +    assert_equal "custom_pattern/another", templates[1].virtual_path +  end +end  | 
