Skip to content
This repository
tree: 3c1187699a
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 188 lines (154 sloc) 5.019 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
require "action_view/template/path"

module ActionView #:nodoc:
  class Template
    extend TemplateHandlers
    extend ActiveSupport::Memoizable
    
    module Loading
      def load!
        @cached = true
        # freeze
      end
    end
    include Loading
    
    include Renderable

    # Templates that are exempt from layouts
    @@exempt_from_layout = Set.new([/\.rjs$/])

    # Don't render layouts for templates with the given extensions.
    def self.exempt_from_layout(*extensions)
      regexps = extensions.collect do |extension|
        extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
      end
      @@exempt_from_layout.merge(regexps)
    end

    attr_accessor :template_path, :filename, :load_path, :base_path
    attr_accessor :locale, :name, :format, :extension
    delegate :to_s, :to => :path

    def initialize(template_path, load_paths = [])
      template_path = template_path.dup
      @load_path, @filename = find_full_path(template_path, load_paths)
      @base_path, @name, @locale, @format, @extension = split(template_path)
      @base_path.to_s.gsub!(/\/$/, '') # Push to split method

      # Extend with partial super powers
      extend RenderablePartial if @name =~ /^_/
    end
    
    def accessible_paths
      paths = []

      if valid_extension?(extension)
        paths << path
        paths << path_without_extension
        if multipart?
          formats = format.split(".")
          paths << "#{path_without_format_and_extension}.#{formats.first}"
          paths << "#{path_without_format_and_extension}.#{formats.second}"
        end
      else
        # template without explicit template handler should only be reachable through its exact path
        paths << template_path
      end

      paths
    end
    
    def relative_path
      path = File.expand_path(filename)
      path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
      path
    end
    memoize :relative_path
    
    def source
      File.read(filename)
    end
    memoize :source
    
    def exempt_from_layout?
      @@exempt_from_layout.any? { |exempted| path =~ exempted }
    end
    
    def path_without_extension
      [base_path, [name, locale, format].compact.join('.')].compact.join('/')
    end
    memoize :path_without_extension

    def path_without_format_and_extension
      [base_path, [name, locale].compact.join('.')].compact.join('/')
    end
    memoize :path_without_format_and_extension
    
    def path
      [base_path, [name, locale, format, extension].compact.join('.')].compact.join('/')
    end
    memoize :path
    
    def mime_type
      Mime::Type.lookup_by_extension(format) if format && defined?(::Mime)
    end
    memoize :mime_type
    
  private
    
    def format_and_extension
      (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
    end
    memoize :format_and_extension

    def multipart?
      format && format.include?('.')
    end

    def content_type
      format.gsub('.', '/')
    end

    def mtime
      File.mtime(filename)
    end
    memoize :mtime

    def method_segment
      relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
    end
    memoize :method_segment

    def stale?
      File.mtime(filename) > mtime
    end

    def recompile?
      !@cached
    end

    def valid_extension?(extension)
      !Template.registered_template_handler(extension).nil?
    end

    def valid_locale?(locale)
      I18n.available_locales.include?(locale.to_sym)
    end

    def find_full_path(path, load_paths)
      load_paths = Array(load_paths) + [nil]
      load_paths.each do |load_path|
        file = load_path ? "#{load_path.to_str}/#{path}" : path
        return load_path, file if File.file?(file)
      end
      raise MissingTemplate.new(load_paths, path)
    end

    # Returns file split into an array
    # [base_path, name, locale, format, extension]
    def split(file)
      if m = file.to_s.match(/^(.*\/)?([^\.]+)\.(.*)$/)
        base_path = m[1]
        name = m[2]
        extensions = m[3]
      else
        return
      end

      locale = nil
      format = nil
      extension = nil

      if m = extensions.split(".")
        if valid_locale?(m[0]) && m[1] && valid_extension?(m[2]) # All three
          locale = m[0]
          format = m[1]
          extension = m[2]
        elsif m[0] && m[1] && valid_extension?(m[2]) # Multipart formats
          format = "#{m[0]}.#{m[1]}"
          extension = m[2]
        elsif valid_locale?(m[0]) && valid_extension?(m[1]) # locale and extension
          locale = m[0]
          extension = m[1]
        elsif valid_extension?(m[1]) # format and extension
          format = m[0]
          extension = m[1]
        elsif valid_extension?(m[0]) # Just extension
          extension = m[0]
        else # No extension
          format = m[0]
        end
      end

      [base_path, name, locale, format, extension]
    end
  end
end
Something went wrong with that request. Please try again.