lib/mustache_render/mustache.rb in mustache_render-0.0.21 vs lib/mustache_render/mustache.rb in mustache_render-0.0.22

- old
+ new

@@ -1,9 +1,9 @@ # -*- encoding : utf-8 -*- -require 'mustache_render/mustache/template' -require 'mustache_render/mustache/context' -require 'mustache_render/mustache/data' +require "#{File.dirname(__FILE__)}/mustache/template" +require "#{File.dirname(__FILE__)}/mustache/context" +require "#{File.dirname(__FILE__)}/mustache/data" module MustacheRender class Mustache def self.render(*args) new.render(*args) @@ -18,23 +18,25 @@ def media @media ||= config.default_render_media end def render(data = template, ctx = {}) - impl_logger :level => :debug, :operation => 'MustacheRender::Mustache.render' do - impl_template_render data, ctx - end - end + self.template = data - # TODO: 语法检查,片段树 - def partials_tree + return self.template.render(context) if ctx == {} + begin + context.push(ctx) + self.template.render(context) + ensure + context.pop + end end # Context accessors. # - # view = ::MustacheRender::Mustache.new + # view = Mustache.new # view[:name] = "Jon" # view.template = "Hi, {{name}}!" # view.render # => "Hi, Jon!" def [](key) context[key.to_sym] @@ -49,34 +51,37 @@ # and want access to the hash currently being iterated over. def context @context ||= Context.new(self) end - # 使用default_media 进行渲染 - def self.impl_render(name, context={}) - self.new.send :impl_render, name, context - end - - def impl_render name, context={} - send "#{::MustacheRender.config.default_render_media}_render".to_sym, name, context - end - # Given a file name and an optional context, attempts to load and # render the file as a template. def self.file_render(name, context = {}) self.new.file_render name, context end # Given a file name and an optional context, attempts to load and # render the file as a template. def file_render(name, context = {}) - impl_logger :level => :debug, :operation => "#{self.class}.file_render" do - @media = :file - render(partial(name), context) - end + @media = :file + render(partial(name), context) end + def self.db_render(full_path, context={}) + self.new.db_render full_path, context + end + + def db_render(full_path, context={}) + @media = :db + render(partial(full_path), context) + end + + def impl_read_db_template name + db_template = ::MustacheRenderTemplate.find_with_full_path(name) + db_template.try :content + end + def self.generate_template_name(name, template_extension) # 如果路径中以扩展名结尾,则直接去取这个文件 name = name.to_s.strip if name.start_with?('/') @@ -96,44 +101,32 @@ begin File.read full_path rescue if config.raise_on_file_template_miss? - raise ::MustacheRender::Mustache::TemplateMiss.new("read file template error: #{full_path}") + raise ::MustacheRender::MustacheTemplateMissError.new("miss read file template error: #{full_path}") else '' end end end def read_template_from_media name, media - # ::MustacheRender.logger.debug "MustacheRender render -> read template from #{media}: #{name}" - - impl_logger :level => :debug, - :operation => "MustacheRender render -> read template from #{media}: #{name}" do - - case media - when :file - # if ::MustacheRender.config.file_template_cache? - # self.class.fetch_partial_cache name, media, :expires_in => ::MustacheRender.config.file_template_cache_expires_in do - # impl_read_file_template name - # end - # else - # impl_read_file_template name - # end - - impl_read_file_template name - end + ::MustacheRender.logger.debug "MustacheRender render -> read template from #{media}: #{name}" + case media + when :file + impl_read_file_template name end end # Override this in your subclass if you want to do fun things like # reading templates from a database. It will be rendered by the # context, so all you need to do is return a string. def partial(name) name = self.class.generate_template_name name, config.file_template_extension + # return self.read_template_from_media name, media @_cached_partials ||= {} (@_cached_partials[media] ||= {})[name] ||= self.read_template_from_media name, media end # Override this to provide custom escaping. @@ -147,10 +140,60 @@ # Returns a String def escapeHTML(str) CGI.escapeHTML(str) end + # + # Private API + # + + # When given a symbol or string representing a class, will try to produce an + # appropriate view class. + # e.g. + # Mustache.view_namespace = Hurl::Views + # Mustache.view_class(:Partial) # => Hurl::Views::Partial + def self.view_class(name) + if name != classify(name.to_s) + name = classify(name.to_s) + end + + # Emptiness begets emptiness. + if name.to_s == '' + return Mustache + end + + file_name = underscore(name) + + name = "#{view_namespace}::#{name}" + + if const = const_get!(name) + const + elsif File.exists?(file = "#{view_path}/#{file_name}.rb") + require "#{file}".chomp('.rb') + const_get!(name) || Mustache + else + Mustache + end + end + + # Supercharged version of Module#const_get. + # + # Always searches under Object and can find constants by their full name, + # e.g. Mustache::Views::Index + # + # name - The full constant name to find. + # + # Returns the constant if found + # Returns nil if nothing is found + def self.const_get!(name) + name.split('::').inject(Object) do |klass, name| + klass.const_get(name) + end + rescue NameError + nil + end + # Has this template already been compiled? Compilation is somewhat # expensive so it may be useful to check this before attempting it. def self.compiled? @template.is_a? Template end @@ -178,11 +221,11 @@ part[0] = part[0].chr.upcase; part end.join end.join('::') end - # TemplatePartial => template_partial + # TemplatePartial => template_partial # Template::Partial => template/partial # Takes a string but defaults to using the current class' name. def self.underscore(classified = name) classified = name if classified.to_s.empty? classified = superclass.name if classified.to_s.empty? @@ -217,44 +260,7 @@ # # Returns the inherited or default configuration setting. def self.inheritable_config_for(attr_name, default) superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default end - - private - - def impl_logger options={} - level = options[:level] || :debug - - result = nil - - if block_given? - start_at = Time.now - result = yield - ms = ((Time.now - start_at) * 1000).to_i - MustacheRender.logger.send level, impl_format_log_entry( - "#{options[:operation]} (#{ms}ms)", options[:message] - ) - end - - result - end - - def impl_format_log_entry(operation, message = nil) - " \033[4;34;1m#{operation}\033[0m \033[0;1m#{message}\033[0m" - end - - def impl_template_render(data=template, ctx={}) - self.template = data - - return self.template.render(context) if ctx == {} - - begin - context.push(ctx) - self.template.render(context) - ensure - context.pop - end - end - end end