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