Module: Nitro::Render

Includes:
BufferHelper
Included in:
Context
Defined in:
lib/nitro/render.rb,
lib/nitro/cgi/stream.rb,
lib/nitro/cgi/send_file.rb

Overview

The rendering mixin. This module is typically included in published objects and/or controllers to provide rendering functionality. – TODO: handle template_root here instead of the controller. ++

Defined Under Namespace

Classes: Emitter

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#action_nameObject

The name of the currently executing action.



85
86
87
# File 'lib/nitro/render.rb', line 85

def action_name
  @action_name
end

#contextObject Also known as: ctx

The context.



70
71
72
# File 'lib/nitro/render.rb', line 70

def context
  @context
end

#controllerObject

The current controller class.



89
90
91
# File 'lib/nitro/render.rb', line 89

def controller
  @controller
end

#outObject Also known as: body

The output buffer. The output of a script/action is accumulated in this buffer.



64
65
66
# File 'lib/nitro/render.rb', line 64

def out
  @out
end

#rendering_errorsObject

An array holding the rendering errors for this request.



81
82
83
# File 'lib/nitro/render.rb', line 81

def rendering_errors
  @rendering_errors
end

#requestObject

Aliases for context.



76
77
78
# File 'lib/nitro/render.rb', line 76

def request
  @request
end

#responseObject

Aliases for context.



76
77
78
# File 'lib/nitro/render.rb', line 76

def response
  @response
end

Instance Method Details

#initialize(context) ⇒ Object

Initialize the render.

context

A parent render/controller acts as the context.



96
97
98
99
# File 'lib/nitro/render.rb', line 96

def initialize(context)
  @request = @response = @context = context
  @out = context.out
end

#render(path) ⇒ Object

Renders the action denoted by path. The path is resolved by the dispatcher to get the correct controller.

Both relative and absolute paths are supported. Relative paths are converted to absolute by prepending the mount path of the controller.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/nitro/render.rb', line 109

def render(path)
  # Convert relative paths to absolute paths.
  path = "#{self.class.mount_path}/#{path}".squeeze('/') unless path =~ /^\//
    
  Logger.debug "Rendering '#{path}'." if $DBG

  @controller, action = @context.dispatcher.dispatch(path.to_s, @context)

  raise 'No controller for action' unless @controller

  # FIXME: 
  @context.content_type = @controller.instance_variable_get('@content_type') || 'text/html'

  @context.level += 1
  old_controller = Controller.replace_current(@controller)
  
  if self.class == @controller 
    self.send(action)
  else
    @controller.new(@context).send(action)
  end

  Controller.replace_current(old_controller)
  @context.level -= 1
  
rescue ActionError => e1
  log_error(e1, path, false)
  print '(error)'

rescue RenderExit, ActionExit => e2

  # Just stop rendering. For example called by redirects.
  
rescue Exception, StandardError => e3
  # More fault tolerant, only flags the erroneous box with 
  # error not the full page.    

  log_error(e3, path)
  print '(error)'
end

#send_file(fname = nil, fullpath = false) ⇒ Object Also known as: sendfile

Send a file download to the client.

Like render and redirect, the action is exited upon calling

fname

That name of the file

path

Specifying true mean fname contains the full path.

The default, false, uses Server.public_root as the path.
return

true on success, false on failure

Examples

require ‘nitro/cgi/send_file’

class MyController < Nitro:Controller

def download(fname)
  send_file(fname)
end

end

class MyController < Nitro:Controller

def download()
  send_file('/etc/password', true)
end

end

Raises:



33
34
35
36
37
38
39
40
41
# File 'lib/nitro/cgi/send_file.rb', line 33

def send_file(fname=nil, fullpath=false)
  fname = fullpath ? fname : "#{Server.public_root}/#{fname}"
  f = File.open(fname, "rb")
  @context.response_headers["Cache-control"] = 'private'
  @context.response_headers["Content-Length"] = "#{File.size?(f) || 0}"
  @context.response_headers["Content-Type"] = 'application/force-download'
  @context.out = f
  raise RenderExit
end

#stream(io = nil) ⇒ Object

Enable streaming mode for the current HTTP Response. You can optionally provide an existing IO object for streaming. – This code is considered a hack fix. But it still is useful so for the moment it stays in the distribution. ++



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/nitro/cgi/stream.rb', line 15

def stream(io = nil)
  if io
    # Reuse an existing IO if it exists.
    @context.out = io
  else  
    r, w = IO.pipe
    
    @context.out = r
    @out = w
    r.sync = true    
    w.class.send(:define_method, :empty?) { false }

    Thread.new do 
      begin
        yield
      ensure
  w.close
      end
    end
  end
end