diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/zero/renderer.rb | 143 |
1 files changed, 65 insertions, 78 deletions
diff --git a/lib/zero/renderer.rb b/lib/zero/renderer.rb index 40a9bed..3e9f790 100644 --- a/lib/zero/renderer.rb +++ b/lib/zero/renderer.rb @@ -1,98 +1,85 @@ module Zero - class FileNotFoundError < IOError; end - # This class helps with rendering of content. + # the base renderer for getting render containers # - # The purpose of this class is to render templates. All variables pushed into - # the renderer should be already processed, so that the raw data can be used. + # This class handles templates and render coontainers, which can be used for + # the actual rendering. # - # The workflow of this class is like the following. + # To use this renderer you have to give it a template path and optionally + # a map of shorthand type descriptions to fully types. This will then be used + # to extend the internal map of templates to possible formats in a way, that + # you will be able to answer xhtml and html requests with the same template. # - # * setup the type mapping - # * create a new instance of the class to prepare rendering - # * call #render to process the template + # When the object is initialized and you are sure, everything is loaded, call + # #read_template_path! and the template tree will be built. Without this step, + # you will probably don't get any output. # - # The call to #render will return the String representation of the template - # with all data given. + # After the setup, the renderer can be used to build render containers, which + # then can be used to actually render something. class Renderer - class << self - # set a base path for template search - # @param path [String] the path to the template base dir - def template_path=(path) - @@path = path + '/' - end - - # save a mapping hash for the type - # - # With that it is possible to map long and complex contant types to simpler - # representations. These get then used in the finding process for the best - # fitting template. - # - # @example - # Zero::Renderer.map = {'text/html' => 'html'} - # - # @param map [Hash] maps the content type to a simple representation - def type_map=(map) - @@map = map - end - - # returns the type map - # @return [Hash] the mapping for types - def type_map - @@map ||= {} - end - end - - # take the path and render the template within the context - # @param path [String] the relative path to the template - # @param context [Object] the object to process on - # @param accept_types - def initialize(path, context, accept_types) - accept_types ||= Request::Accept.new('text/html') - @path = find_template(path, accept_types) - @context = context - end - - # render the template within the context - # @return [String] the rendered template - def render - Tilt.new(@path).render(@context) + # initializes a new Renderer + # + # This method takes a path to the base template directory and a type map. + # This type map is used to extend the possible renderings for different + # types, which the clients sends. + # + # @example create a simple renderer + # Renderer.new('app/templates') + # + # @example create a renderer with a small map + # Renderer.new('app', { + # 'html' => ['text/html', 'application/html+xml'], + # 'json' => ['application/json', 'application/aweomse+json'] + # }) + # + # @param [String] a string to templates + def initialize(template_path, type_map = {}) + @template_path = template_path + '/' + @type_map = type_map end - private - - # check if the template does exist + # returns the hash of type conversions + # @return [Hash] type conversion + attr_reader :type_map + # get the path to the templates + # @return [String] the base template path + attr_reader :template_path + # get the tree of templates # @api private - # @param template_path [String] the relative path to the template - # @param types [Array] a sorted list of types to search for - # @return [String] a file name to use - def find_template(template_path, types) - types.each do |type| - Dir[@@path + template_path + '.' + transform(type) + '.*'].each do |file| - return file + # @return [Hash] the template tree + attr_reader :templates + + # load the template tree + # + # This method gets all templates in the `template_path` and builds an + # internal tree structure, where templates and types direct the request to + # the wanted template. + def read_template_path! + @templates = Hash.new do |hash, key| + subtree = {} + search_files(key).each do |file| + parts = file.split('.') + read_type(parts[2]).each do |type| + subtree[type] = file + end end + hash[key] = subtree end - raise FileNotFoundError.new("Template '#{template_path}' not found!") + self end - # @see transform - # @api private - def transform(string) - self.class.transform(string) + private + + def search_files(template_name) + Dir[template_path + template_name + '**/*.*'] end - # transform a type into a simpler representation - # @api private - # @param string [String] the original type name - # @return [String] the shorter representation or the original - def self.transform(string) - return type_map[string] if type_map.has_key?(string) - string + def read_type(short_notation) + to_type_list(type_map[short_notation] || short_notation) end - # an alias to Renderer.map - # @api private - def map - self.class.map + def to_type_list(original_map) + return original_map if original_map.respond_to?(:each) + [original_map] end end end |