Class: Closure::Script
- Inherits:
-
Rack::Request
- Object
- Rack::Request
- Closure::Script
- Defined in:
- lib/closure/script.rb
Overview
A Closure::Script instance is the context in which scripts are rendered. It inherits everything from Rack::Request and supplies a Response instance you can use for redirects, cookies, and other controller actions.
Defined Under Namespace
Classes: NotFound, RenderStackOverflow
Constant Summary collapse
- ENV_ERROR_CONTENT_TYPE =
'closure.error.content_type'
Instance Attribute Summary collapse
-
#goog ⇒ Goog
All the cool stuff lives here.
-
#render_stack ⇒ <Array>
readonly
An array of filenames representing the current render stack.
-
#response ⇒ Rack::Response
After rendering, #finish will be sent to the client.
Instance Method Summary collapse
-
#expand_path(filename, dir = nil) ⇒ String
Helper for finding files relative to Scripts.
-
#expand_src(filename, dir = nil) ⇒ String
Helper to locate a file as a file server path.
-
#initialize(env, sources, filename) ⇒ Script
constructor
A new instance of Script.
-
#relative_src(filename, dir = nil) ⇒ String
Helper to locate a file as a file server path.
-
#render(filename, locals = {}) ⇒ Object
Render another Script.
Constructor Details
#initialize(env, sources, filename) ⇒ Script
Returns a new instance of Script.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/closure/script.rb', line 32 def initialize(env, sources, filename) super(env) @render_stack = [] @goog = Goog.new(env, sources, @render_stack) @response = original_response = Rack::Response.new rendering = render(filename) if @response == original_response and @response.empty? @response.write rendering end rescue RenderStackOverflow, NotFound => e if @render_stack.size > 0 # Make errors appear from the render instead of the engine.call e.set_backtrace e.backtrace[1..-1] env[ENV_ERROR_CONTENT_TYPE] = @response.finish[1]["Content-Type"] rescue nil raise e end @response.status = 404 @response.write "404 Not Found\n" @response.header["X-Cascade"] = "pass" @response.header["Content-Type"] = "text/plain" rescue StandardError, LoadError, SyntaxError => e env[ENV_ERROR_CONTENT_TYPE] = @response.finish[1]["Content-Type"] rescue nil raise e end |
Instance Attribute Details
#goog ⇒ Goog
All the cool stuff lives here.
65 66 67 |
# File 'lib/closure/script.rb', line 65 def goog @goog end |
#render_stack ⇒ <Array> (readonly)
An array of filenames representing the current render stack.
76 77 78 |
# File 'lib/closure/script.rb', line 76 def render_stack @render_stack end |
#response ⇒ Rack::Response
After rendering, #finish will be sent to the client. If you replace the response or add to the response#body, the script engine rendering will not be added.
61 62 63 |
# File 'lib/closure/script.rb', line 61 def response @response end |
Instance Method Details
#expand_path(filename, dir = nil) ⇒ String
Helper for finding files relative to Scripts.
127 128 129 130 |
# File 'lib/closure/script.rb', line 127 def (filename, dir=nil) dir ||= File.dirname render_stack.last File. filename, dir end |
#expand_src(filename, dir = nil) ⇒ String
Helper to locate a file as a file server path.
135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/closure/script.rb', line 135 def (filename, dir=nil) filename = filename, dir src = nil @goog.each do |directory, path| dir_range = (directory.length..-1) if filename.index(directory) == 0 src = "#{path}#{filename.slice(dir_range)}" break end end raise Errno::ENOENT unless src src end |
#relative_src(filename, dir = nil) ⇒ String
Helper to locate a file as a file server path.
152 153 154 155 156 |
# File 'lib/closure/script.rb', line 152 def relative_src(filename, dir=nil) file = filename, dir base = Pathname.new File.dirname path_info Pathname.new(file).relative_path_from(base).to_s end |
#render(filename, locals = {}) ⇒ Object
Render another Script.
83 84 85 86 87 88 89 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 |
# File 'lib/closure/script.rb', line 83 def render(filename, locals = {}) if render_stack.size > 100 # Since nobody sane should recurse through here, this mainly # finds a render self that you might get after a copy and paste raise RenderStackOverflow elsif render_stack.size > 0 # Hooray for relative paths and easily movable files filename = File.(filename, File.dirname(render_stack.last)) else # Underbar scripts are partials by convention; keep them from rendering at root filename = File.(filename) raise NotFound if File.basename(filename) =~ /^_/ end fext = File.extname(filename) files1 = [filename] files1 << filename + '.html' if fext == '' files1 << filename.sub(/.html$/,'') if fext == '.html' files1.each do |filename1| Closure.config.engines.each do |ext, engine| files2 = [filename1+ext] files2 << filename1.gsub(/.html$/, ext) if File.extname(filename1) == '.html' unless filename1 =~ /^_/ or render_stack.empty? files2 = files2 + files2.collect {|f| "#{File.dirname(f)}/_#{File.basename(f)}"} end files2.each do |filename2| if File.file?(filename2) and File.readable?(filename2) if render_stack.empty? response.header["Content-Type"] = Rack::Mime.mime_type(File.extname(filename1), 'text/html') end render_stack.push filename2 @goog.add_dependency filename2 result = engine.call self, locals render_stack.pop return result end end end end raise NotFound end |