Class: N::App::CodeHandler
- Inherits:
-
ScriptHandler
- Object
- ServerFilter
- Handler
- ScriptHandler
- N::App::CodeHandler
- Defined in:
- lib/n/app/handlers/code-handler.rb
Overview
CodeHandler
web server handler that executes ruby code (logic) Caching is NOT SUPPORTED (and not needed anyway)
TODO:
probably extend PageHandler from CodeHandler and not vice versa.
Instance Attribute Summary
Attributes inherited from ServerFilter
Instance Method Summary collapse
- #calc_script_key(path, hash) ⇒ Object
-
#eval_script(script, request) ⇒ Object
evaluate the request script in the context of the current request.
-
#get_compiled_script(path, hash = nil) ⇒ Object
try to get the script from the cache.
-
#process(request) ⇒ Object
process is called ONLY for top level scripts.
-
#transform_script(path, hash, shader = nil) ⇒ Object
Output: defcode: the code that customizes the base script class.
Methods inherited from ScriptHandler
#compile_script, #compiled_script_cache, #log_error, #overload_path
Methods inherited from ServerFilter
#<<, #initialize, #process_next
Constructor Details
This class inherits a constructor from N::ServerFilter
Instance Method Details
#calc_script_key(path, hash) ⇒ Object
163 164 165 |
# File 'lib/n/app/handlers/code-handler.rb', line 163 def calc_script_key(path, hash) return "#{path}#{hash}".gsub(/[^\w]/, "") end |
#eval_script(script, request) ⇒ Object
evaluate the request script in the context of the current request. returns the output of the script, ie the fragment body.
Design:
I think that the script caching logic should be here, because it nicelly encapsulates transform and compile.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/n/app/handlers/code-handler.rb', line 62 def eval_script(script, request) $log.debug "Evaluating, #{request.path}" if $DBG fragment = Fragment.new(:key) # try to render the script, report errors. begin fragment.body = script.__render(request) rescue N::ScriptExitException => see # the script raised a ScripteExitException to force a premature # end. Surpress this error! rescue => ex log_error(request, ex) end return fragment end |
#get_compiled_script(path, hash = nil) ⇒ Object
try to get the script from the cache. invalidates the compiled version and return nil if the script is modified since compile time. Also takes active shader and localization into account. If script is not compiled, transform and compile it.
Output: the compiled script. Throws exception if the script does not exist.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/n/app/handlers/code-handler.rb', line 132 def get_compiled_script(path, hash = nil) compiled_script = nil key = calc_script_key(path, hash) # gmosx: $reload_scripts is typically set to true when debugging # statically included files (.ss) unless $reload_scripts compiled_script = @@compiled_script_cache[key] # gmosx: monitor scripts should be explicit! if $srv_monitor_scripts and compiled_script and (File.mtime(compiled_script.path) > compiled_script.__create_time) $log.debug "Script '#{path}' externaly modified, recompiling" if $DBG compiled_script = nil end end unless compiled_script # the script is not cached, so load, transform and compile it! $log.debug "Compiling script '#{key}'" if $DBG script = transform_script(path, key) compiled_script = compile_script(script) @@compiled_script_cache[key] = compiled_script end return compiled_script end |
#process(request) ⇒ Object
process is called ONLY for top level scripts.
no need for synchronization, the page-script is thread safe. if you use thread-unsafe code in your script you are responsible for synchronization.
TODO: add timing code here
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/n/app/handlers/code-handler.rb', line 41 def process(request) # gmosx, FIXME: temporarily here, move somewhere ELSE! request.locale = $lc_map[request.user.locale] || $lc_en script = get_compiled_script(request.path) fragment = eval_script(script, request) # walk the filter pipeline super return fragment, script end |
#transform_script(path, hash, shader = nil) ⇒ Object
Output:
defcode: the code that customizes the base script class. pagecode: the code that renders the fragment.
REMARKS:
-
this method is evaluated in compile time, so we cannot pass or use the request/request pair. gmosx: NO, we do pass request, some data can and SHOULD be used to prepare the transform.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/n/app/handlers/code-handler.rb', line 90 def transform_script(path, hash, shader = nil) path = overload_path(path) # load the page text from the script pagecode = "" pagecode = File.read("#$root_dir/#{path}") # convert to ruby code pagecode.gsub!(/<<</, "__out << %{") pagecode.gsub!(/>>>/, "}") script = %{ class CodeScript_#{hash} < CodeScript def initialize(path) super @pagecode = <<-'PAGECODE' #{pagecode} PAGECODE @defcode = nil end def __render(request) __out = "" lc = request.locale #{pagecode} return __out end end return CodeScript_#{hash}.new("#{path}") } return script end |