Class: Exocora::Sheet

Inherits:
Object
  • Object
show all
Defined in:
lib/exocora/sheet.rb

Overview

A single CGI script. Requests are processed through a chain of actions

validate - extract and sanitize data from the CGI request process - do stuff render - render to the specified template.

Constant Summary collapse

@@validations =

Parameters with validations

Hash.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSheet

Returns a new instance of Sheet.



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/exocora/sheet.rb', line 13

def initialize
  @cgi = CGI.new
  @headers = {
  }
  
  @params = {}
  @errors = {}
  
  @template = self.class.to_s.module_path
  @log_file = self.class.to_s.underscore + '.log'
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



11
12
13
# File 'lib/exocora/sheet.rb', line 11

def errors
  @errors
end

#paramsObject (readonly)

Returns the value of attribute params.



11
12
13
# File 'lib/exocora/sheet.rb', line 11

def params
  @params
end

Class Method Details

.runObject

Creates an instance of this sheet, and runs it.



41
42
43
# File 'lib/exocora/sheet.rb', line 41

def self.run
  new.run
end

.validate(param, message = 'must be valid', &block) ⇒ Object

Adds a validation condition for a parameter. validate :query { |q| q.size > 0 } validate :query, “is invalid” { |q|



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/exocora/sheet.rb', line 28

def self.validate(param, message='must be valid', &block)
  validation = Validation.new(nil, message)
  if block_given?
    validation.when block
  end

  @@validations[param.to_s] ||= []
  @@validations[param.to_s] << validation
  
  validation
end

Instance Method Details

#cast_params(params) ⇒ Object

Casts incoming CGI parameters to nil, numerics, collapses single-element arrays, and so forth.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/exocora/sheet.rb', line 47

def cast_params(params)
  cast = {}
  params.each do |key, values|
    cast_values = values.map do |value|
      if value =~ /^\d+$/
        value.to_i
      elsif value =~ /^[\d.]+$/
        value.to_f
      else
        value
      end
    end

    if values.empty?
      cast[key] = nil
    elsif values.size == 1
      cast[key] = cast_values.first
    else
      cast[key] = cast_values
    end
  end

  cast
end

#log(message) ⇒ Object

Logs a message to a file.



73
74
75
76
77
# File 'lib/exocora/sheet.rb', line 73

def log(message)
  File.open(@log_file, 'a') do |file|
    file.puts message
  end
end

#log_to(file) ⇒ Object

Chooses the file for logging.



80
81
82
# File 'lib/exocora/sheet.rb', line 80

def log_to(file)
  @log_file = file
end

#output(string) ⇒ Object

Sends output to the client. The first time output is called, it sends an HTTP header first.



86
87
88
89
90
91
92
93
# File 'lib/exocora/sheet.rb', line 86

def output(string)
  unless @headers_sent
    puts @cgi.header(@headers)
    @headers_sent = true
  end

  puts string
end

#processObject

Process is the meat of the script. It returns a hash like => 2, which become instance variables @a = 2 in the template.



98
99
# File 'lib/exocora/sheet.rb', line 98

def process
end

#redirect_to(uri_fragment) ⇒ Object

Breaks the normal rendering flow, and outputs an HTTP redirect header.



102
103
104
105
106
# File 'lib/exocora/sheet.rb', line 102

def redirect_to(uri_fragment)
  @headers['Status'] = '302 Moved'
  @headers['Location'] = @cgi.full_uri_for uri_fragment
  output
end

#render(context = Erubis::Context.new) ⇒ Object

Renders the erubis template for this action. Takes a hash of variables to render. The default template is determined by underscoring this sheet’s class name, but another template can be specified using #template.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/exocora/sheet.rb', line 111

def render(context = Erubis::Context.new)
  # Read template data
  template_filename = "#{@template}.rhtml"
  begin
    template = File.read(template_filename)
  rescue Errno::ENOENT
    raise ScriptError.new("Template #{template_filename} does not exist!")
  end

  # Prepare template and variables
  eruby = Erubis::Eruby.new template
  
  # Perform templating
  begin
    result = eruby.evaluate context
  rescue
    raise TemplateError.new("Encountered error processing template #{template_filename}.", $!)
  end

  # Output result
  output result 
end

#requestObject

Accessor for the CGI object



135
136
137
# File 'lib/exocora/sheet.rb', line 135

def request
  @cgi
end

#runObject

This is the action which initiates processing of the script.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/exocora/sheet.rb', line 140

def run
  begin
    # Cast parameters
    @params = cast_params @cgi.params

    # Check parameters
    validate

    # Run process
    context = process

    # Render output
    render context
  rescue
    # Handle errors
    output "<html><head><title>Exocora Error</title></head><body>"
    output "<h1>#{$!.class}</h1>"

    output $!.to_html

    output "</body></html>"
  end
end

#use_template(template) ⇒ Object

Sets the name of the template to render.



165
166
167
# File 'lib/exocora/sheet.rb', line 165

def use_template(template)
  @template = template
end

#valid?(param = nil) ⇒ Boolean

Returns true if the specified (or all) parameters have no errors.

Returns:

  • (Boolean)


170
171
172
173
174
175
176
# File 'lib/exocora/sheet.rb', line 170

def valid?(param = nil)
  if param.nil?
    @errors.empty?
  else
    @errors[param].nil? or @errors[param].empty?
  end
end

#validate(params = @params) ⇒ Object

Validates CGI parameters according to @@validations.

Parameters which fail validation have entries recorderd in @errors.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/exocora/sheet.rb', line 181

def validate(params = @params)
  @@validations.each do |param, validations|
    validations.each do |validation|
      values = params[param]

      # If there are multiple values, check each one.
      unless values.kind_of? Array
        values = [values]
      end
 
      values.each do |value| 
        begin
          validation.validate(value)
        rescue ValidationError => e
          @errors[param] ||= []
          @errors[param] << e
        end
      end
    end
  end

  params
end