require 'monitor' require 'delegate' require 'core-ext/string' require 'core-ext/nilclass' module SimpleView autoload :FileContent, File.join(File.dirname(__FILE__), 'file_content') autoload :Renderable, File.join(File.dirname(__FILE__), 'renderable') autoload :SimpleViewERB, File.join(File.dirname(__FILE__), 'erb_view') autoload :SimpleViewIO, File.join(File.dirname(__FILE__), 'io_view') autoload :SimpleViewBuilder, File.join(File.dirname(__FILE__), 'builder_view') autoload :SimpleViewPOI, File.join(File.dirname(__FILE__), 'poi_view') $SV_DEBUG = ENV['SV_DEBUG'] class Base class << self attr_accessor :directory_views, :directory_helpers end def directory_views Base.directory_views end def directory_helpers Base.directory_helpers end end class TemplateViewNotFound < Exception; end class SimpleViewBase < Base attr_accessor :template, :file_template def initialize(template, file_template = nil) self.template = template self.file_template = file_template end def template_name(ext = self.template_extension) "#{template}#{ext}" end def lookup_file_template(ext = self.template_extension) unless @file_template tpl = self.template_name(ext) list = Dir.glob(File.join(self.directory_views, tpl)) raise TemplateViewNotFound.new("Impossible de trouver le template #{tpl} dans le repertoire #{self.directory_views}") unless list.size == 1 @file_template = list.first end @file_template end def clean_template_name_for_helper template[/(\w+)(\W*)/,1] end def lookup_file_helper if !self.instance_variable_defined?(:@file_helper) && self.directory_helpers helper_file_name = "#{self.clean_template_name_for_helper}_helper.rb" puts "SimpleViewBase > helper_file_name= #{helper_file_name}" if $DEBUG fhlpr = File.join(self.directory_helpers, helper_file_name) puts "SimpleViewBase > fhlpr= #{fhlpr}" if $DEBUG if File.exist?(fhlpr) @file_helper = FileContent.file(fhlpr) end end @file_helper end def template_content FileContent.file(self.lookup_file_template).content end def has_helper? hf = self.lookup_file_helper return nil unless hf true end def helper_module_name hname = self.clean_template_name_for_helper # exemple: template = 'etat_corbeilles_prc.html' => hname = 'etat_corbeilles_prc' "#{hname}_helper".camelcase(true).to_sym end def template_extension if self.class.respond_to?(:extension) return self.class.extension end ".rb" end def set_helper(rendable_object) if has_helper? helper = nil helper_name = self.helper_module_name begin if @file_helper.changed? || !Object::const_defined?(helper_name) load @file_helper.file(true) else end helper = Object::const_get(helper_name) rescue NameError => ex # puts "set_helper: #{ex.message}", ex.backtrace require(@file_helper.file) retry end puts "set_helper #{helper} for: #{rendable_object}" if $DEBUG rendable_object.extend helper end end def render(rendable_object, options = {}) target = options[:target] if String === target && (options[:type] != :string) FileUtils.mkdir_p(File.dirname(target)) if options[:mkdirs] open(target, options[:open]||'w') do |o| options[:target] = o begin return do_rendering(rendable_object, options) ensure options[:target] = target end end else return do_rendering(rendable_object, options) end rescue => ex puts ex.message, ex.backtrace.collect{|st| "\t#{st}"} if $SV_DEBUG puts "[SV_DEBUG = #$SV_DEBUG]: Retry ? [y|n]" response = $stdin.gets.strip retry if response =~ /Y|y/ end raise ex end def render_with_helper(rendable_object) set_helper(rendable_object) yield if block_given? end class << self def template_extensions @template_extensions ||= {} end def register(subclass) ext = subclass.extension SimpleViewBase.template_extensions[ext] = subclass end def lookup_file_template(template) tpl = "#{template}#{self.extension}" file = File.join(Base.directory_views, tpl) puts "lookup_file_template : #{tpl} => #{file}" if $DEBUG raise TemplateViewNotFound.new("Impossible de trouver le template #{tpl} dans le repertoire #{Base.directory_views} (#{file})") unless File.exist?(file) file end def views @views ||= {} end def view(template) self.views[template] ||= self.basic_view(template) end def find_view(template) SimpleViewBase.template_extensions.each do |ext, renderer| begin return renderer.view(template) rescue TemplateViewNotFound end end raise TemplateViewNotFound.new("Impossible de trouver le template #{template} dans le repertoire #{Base.directory_views}") end protected def basic_view(template) file = lookup_file_template(template) self.new(template, file) end end end class SimpleLayout < SimpleViewBase def do_rendering(rendable_object, options) end end # Loading default SimpleViewERB.name SimpleViewIO.name end