lib/trellis/trellis.rb in trellis-0.0.2 vs lib/trellis/trellis.rb in trellis-0.0.3

- old
+ new

@@ -36,10 +36,11 @@ require 'haml' require 'markaby' require 'redcloth' require 'bluecloth' require 'english/inflect' +require 'directory_watcher' module Trellis # -- Application -- # Represents a Trellis Web Application. An application can define one or more @@ -69,22 +70,30 @@ end # bootstrap the application def start(port = 3000) Application.logger.info "Starting Trellis Application #{self.class} on port #{port}" + + directory_watcher = configure_directory_watcher + directory_watcher.start + Rack::Handler::Mongrel.run configured_instance, :Port => port do |server| trap(:INT) do Application.logger.info "Exiting Trellis Application #{self.class}" + directory_watcher.stop server.stop end end + rescue Exception => e + Application.logger.warn "#{ e } (#{ e.class })!" end def configured_instance # configure rack middleware application = Rack::ShowStatus.new(self) application = Rack::ShowExceptions.new(application) + application = Rack::Reloader.new(application) application = Rack::CommonLogger.new(application, Application.logger) application = Rack::Session::Cookie.new(application) # set all static resource paths self.class.static_routes.each do |path| @@ -138,10 +147,40 @@ else response.status = 404 end response.finish end + + private + + def configure_directory_watcher(directory = nil) + # set directory watcher to reload templates + glob = [] + Page::TEMPLATE_FORMATS.each do |format| + glob << "*.#{format}" + end + + templates_directory = directory || "#{File.dirname($0)}/../html/" + + directory_watcher = DirectoryWatcher.new templates_directory, :glob => glob, :pre_load => true + directory_watcher.add_observer do |*args| + args.each do |event| + Application.logger.debug "directory watcher: #{event}" + event_type = event.type.to_s + if (event_type == 'modified' || event_type == 'stable') + template = event.path + format = File.extname(template).delete('.').to_sym + page_locator = Page.template_registry[template] + page = Page.get_page(page_locator) + Application.logger.info "reloading template for page => #{page}: #{template}" + File.open(template, "r") { |f| page.template(f.read, :format => format) } + end + end + end + Application.logger.info "watching #{templates_directory} for template changes..." + directory_watcher + end end # -- Route -- # A route object encapsulates an event, the event destination (target), the # event source and an optional event value @@ -269,12 +308,15 @@ # components and it defines a template or view either as an external file # (xml, xhtml, other) or programmatically using Markaby or HAML # A Trellis Page contains listener methods to respond to events trigger by # components in the same page or other pages class Page + + TEMPLATE_FORMATS = [:html, :xhtml, :haml, :textile, :markdown] @@subclasses = Hash.new + @@template_registry = Hash.new attr_accessor :params, :path, :logger def self.inherited(child) #:nodoc: @@subclasses[child.class_to_sym] = child @@ -407,14 +449,24 @@ end def self.inject_dependent_pages(target) @pages.each do |sym| clazz = Page.get_page(sym) - target.instance_variable_set("@#{sym}".to_sym, clazz.new) - target.meta_def(sym) { instance_variable_get("@#{sym}") } + if clazz + Application.logger.debug "injecting an instance of #{clazz} for #{sym}" + target.instance_variable_set("@#{sym}".to_sym, clazz.new) + target.meta_def(sym) { instance_variable_get("@#{sym}") } + else + # throw an exception in production mode or + # dynamically generate a page in development mode + end end end + + def self.template_registry + @@template_registry + end private def self.locate_template(clazz) begin @@ -425,15 +477,18 @@ end base = "#{clazz.underscore_class_name}" Application.logger.debug "looking for template #{base} in #{dir}" - [:xhtml, :haml, :textile, :markdown].each do |format| + TEMPLATE_FORMATS.each do |format| filename = "#{base}.#{format}" file = File.find_first(dir, filename) if file Application.logger.debug "found template for page => #{clazz}: #{filename}" File.open(file, "r") { |f| clazz.template(f.read, :format => format) } + # add the template file to the external template registry so that we can reload it + @@template_registry["#{dir}#{filename}"] = clazz.class_to_sym + Application.logger.debug "registering template file for #{clazz.class_to_sym} => #{dir}#{filename}" break end end rescue Exception => e Application.logger.debug "no template found for page => #{clazz}: #{base} : #{e}" \ No newline at end of file