Class: Doozer::Controller

Inherits:
Object show all
Includes:
Util::Logger, ViewHelpers
Defined in:
lib/doozer/controller.rb

Overview

This is the main Controller class which is inherited by application controllers.

Controllers have access to all ViewHelpers.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ViewHelpers

#alink, #app_name, #app_path, #aurl, #authtoken, #base_url, #feed, #h, #hash_to_props, #hash_to_qs, #img, #ip, #javascript, #link, #metatags, #path, #rack_env, #server_name, #session?, #static_url, #stylesheet, #title, #url

Methods included from Util::Logger

#logger

Constructor Details

#initialize(args = {}) ⇒ Controller

When a Controller is intialized it expects the following args:

args=

:route=>route matched against the request path,
:extra_params=>the route tokens parameterized as a hash,
:port=>the port of the appserver responding to the request

  • :extra_params are turned into instance variables so you can access them directly from controller methods and views. In order to keep a small footprint these aren’t passed into partial classes.

Example: A route of /admin/post/:id and a request path of /admin/post/8 automatically exposes an instance variable of @id with a value of 8 in your controller.

  • query params are accessible via @params hash and are parameterized via Rack.



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
124
125
126
127
128
129
# File 'lib/doozer/controller.rb', line 95

def initialize(args={})
  @route = args[:route]; @env = args[:env]
  @format = @route.format
  @port = args[:port]

  #init request from env
  @request = Rack::Request.new(@env)
  
  #holds all variables for template binding
  @view={}; @view[:meta]={}
  
  #loads flash messages from cookie
  @flash={}; flash_from_cookie()
  
  #loads cookies from cookies
  @cookies={}; cookies_from_cookie()
  
  #loads session cookie
  @session={}; session_from_cookie()
  
  #symbolize params
  @params={}; @request.params.each { |key, value| @params[key.to_sym] = value} 
  
  #set bust key
  @bust_key = (rand(1000) * 1024)
  
  # set up default render_args
  @render_args = {:layout=>nil, :view=>nil, :text=>nil}
  render_args_init()
  
  #turn extra params into instance variables...
  args[:extra_params].each { |key, value| self.instance_variable_set("@#{key}".to_sym, value)}
  puts "  Params: #{@request.params.inspect}" if not @request.params.nil?
  puts "  Extra params: #{args[:extra_params].inspect}" if not args[:extra_params].nil?
end

Instance Attribute Details

#bust_keyObject

Returns the value of attribute bust_key.



48
49
50
# File 'lib/doozer/controller.rb', line 48

def bust_key
  @bust_key
end

#cookiesObject

To save cookies: All hash keys must be symbols and value strings. Reserved hash keys per cookie: :expires - Time.now + some duration. This default to 30 days if not defined :path - The path for the cookie. This defaults to ‘/’ if not defined

Example: @cookies=

:b=>'abc',
:expires=>Time.now + 3.day
:path=>'/path'

To delete a cookie, set it to nil or delete it from @cookies

@cookies=nil



42
43
44
# File 'lib/doozer/controller.rb', line 42

def cookies
  @cookies
end

#envObject

Returns the value of attribute env.



20
21
22
# File 'lib/doozer/controller.rb', line 20

def env
  @env
end

#flashObject

Returns the value of attribute flash.



26
27
28
# File 'lib/doozer/controller.rb', line 26

def flash
  @flash
end

#formatObject

Returns the value of attribute format.



50
51
52
# File 'lib/doozer/controller.rb', line 50

def format
  @format
end

#paramsObject

Returns the value of attribute params.



24
25
26
# File 'lib/doozer/controller.rb', line 24

def params
  @params
end

#portObject

Returns the value of attribute port.



52
53
54
# File 'lib/doozer/controller.rb', line 52

def port
  @port
end

#render_argsObject

Returns the value of attribute render_args.



54
55
56
# File 'lib/doozer/controller.rb', line 54

def render_args
  @render_args
end

#requestObject

Returns the value of attribute request.



22
23
24
# File 'lib/doozer/controller.rb', line 22

def request
  @request
end

#routeObject

Returns the value of attribute route.



18
19
20
# File 'lib/doozer/controller.rb', line 18

def route
  @route
end

#sessionObject

Returns the value of attribute session.



44
45
46
# File 'lib/doozer/controller.rb', line 44

def session
  @session
end

#viewObject

Returns the value of attribute view.



46
47
48
# File 'lib/doozer/controller.rb', line 46

def view
  @view
end

Class Method Details

.include_view_helper(helper) ⇒ Object

Include the app/helpers file_name. Expects helper as a string.

You must pass the full file name if you use this method.

Example: self.include_view_helper(‘application_helper’)



354
355
356
357
# File 'lib/doozer/controller.rb', line 354

def self.include_view_helper(helper)
    # importing view helpers into controller
    include Object.const_get(Doozer::Lib.classify("#{helper}"))
end

.include_view_helpersObject

Include additional view helpers declared for the class.

This method automatically appends ‘_helper’ to each required helper symbol



342
343
344
345
346
347
# File 'lib/doozer/controller.rb', line 342

def self.include_view_helpers
    # importing view helpers into controller
    self.require_view_helpers.each { | sym |
      self.include_view_helper("#{sym.to_s}_helper")
    }
end

Instance Method Details

#after_filterObject

Controller hook called after controller#method call



332
# File 'lib/doozer/controller.rb', line 332

def after_filter; end

#after_initializeObject

Controller hook called after controller#initialize call.

By default, this method automatically checks if the authtoken is present for post requests. It throws an error if it’s missing or has been tampered with.



316
317
318
319
320
321
322
323
324
325
326
# File 'lib/doozer/controller.rb', line 316

def after_initialize
  # test if request == post and if so if authtoken is present and valid
  if @request.post?
    token=@params[:_authtoken]
    if token
      raise "Doozer Authtoken Tampered With!" if not authtoken_matches?(token)
    else
      raise "Doozer Authtoken Missing! By default, post requests require an authtoken. You can override this by adding the action to the after_initialize_exclude list." if not authtoken_matches?(token)
    end
  end
end

#before_filterObject

Controller hook called before controller#method call



329
# File 'lib/doozer/controller.rb', line 329

def before_filter; end

Read all the persistant cookies and store them in the @cookies instance variable



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/doozer/controller.rb', line 257

def cookies_from_cookie
  #split name/value pairs
  if @request.cookies
    @request.cookies.each { | k, v |
      if not ["flash", "session", "rack.session"].include?(k)
        begin
          # we need to catch cookies which don't match the key=value&key=value pattern...
          # google analytics for example
          values = {}
          pairs=v.split('&')
          pairs.each{ | pair | 
            pair = pair.split('=')
            values[pair[0].to_sym]=CGI::unescape(pair[1])
          }
          @cookies[k.to_sym] = values
        rescue
        end
      end
    }
  end
end

#dbObject

Sequel ORM db connection



210
211
212
# File 'lib/doozer/controller.rb', line 210

def db
  Doozer::Configs.db_conn
end

#finished!Object

Global teardown called at the end of every request. Hooks ORM.teardown



335
336
337
# File 'lib/doozer/controller.rb', line 335

def finished!
  Doozer::ORM.after_request if Doozer::Configs.orm_loaded
end

Read all the flash cookies and store them in the @flash instance variable



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/doozer/controller.rb', line 222

def flash_from_cookie
  #split name/value pairs and merge with flash
  if @request.cookies
    if @request.cookies["flash"]
      pairs=@request.cookies["flash"].split('&')
      pairs.each{|pair| 
        pair = pair.split('=')
        @flash[pair[0].to_sym]=CGI::unescape(pair[1])
      }
    end
  end
end

Compile flash keys as name=value array which are stored in the flash cookie. The flash variables are only persisted for one response.



215
216
217
218
219
# File 'lib/doozer/controller.rb', line 215

def flash_to_cookie
  #loop over all flash messages and return as name/value array
  out=[]; @flash.each { |key, value| out.push("#{key}=#{CGI::escape(value.to_s)}") if not value.nil? }
  return out
end

#layout(sym) ⇒ Object

DEPRECATED: use render() instead



309
310
311
# File 'lib/doozer/controller.rb', line 309

def layout(sym)
  raise "Deprecated: Controller#layout; Use render({:layout=>:symbol}) instead"
end

#meta(opt = {}) ⇒ Object

Method for setting metatags via Controllers.

Pass an options hash to @view and all the key/values are turned into metatags with the corresponding values. See Doozer::ViewHelpers#metatags for creating the metatags for view.

Example: meta(awesome metatag description is awesome’, :keywords=>‘awesome, blog, of awesomeness’)



304
305
306
# File 'lib/doozer/controller.rb', line 304

def meta(opt={})
  @view[:meta]=opt
end

#partial(file = nil, locals = {}) ⇒ Object

A method to render a partial from a controller. Expects a file name and optional local variables. See Partial for more details.

By default, the @request variable is appended to locals and available in the partial view.



191
192
193
194
195
196
197
198
# File 'lib/doozer/controller.rb', line 191

def partial(file=nil, locals={})
  # self.instance_variables.each { | k | 
  #   locals[k.gsub(/@/,'').to_s] = eval(k)
  # }
  # p locals.inspect
  locals[:request] = @request
  Doozer::Partial.partial(file, locals, route=@route)
end

#redirect_to(route = {}, opts = {}) ⇒ Object

Redirect the response object to the tokenized route url with optional query string values

The route is passed through the ViewHelpers.url method. See url() for examples.

Raises:



203
204
205
206
207
# File 'lib/doozer/controller.rb', line 203

def redirect_to(route={}, opts={})
  path = url(route)
  # p "Redirect to: #{path}"
  raise Doozer::Redirect.new(path, opts)
end

#render(args = {}) ⇒ Object

Renders an action with any of the following overridable parameters:

args=

:view=>Symbol, String or ERB,
:layout=>Symbol,
:text=>'this is the text to render'

:view - All actions default to a view of views/controller_name/action_name.format.erb which is originated from the route properties.

To override this from controller actions, you can pass any of the following:

  • :view=>:view_name

    This assumes the view is in the same controller as the present action.

  • :view=>‘controller_name/action_name’

    This renders a view from a the provided controller and action and with the format specified in the route.

  • :view=>ERB.new(‘<%=var%> is nice’)

:layout - All actions default to a layout of views/layouts/default.format.erb

To override this from controller actions, you can pass any of the following:

  • :layout=>:layout_name_format or :none (don’t display a layout at all)

    There is no need to specify the format for :html formats.

    Example: :layout=>:some_layout (where format equals :html) or :some_layout_json (where format equals :json)

:text - Overrides all view rendering options and displays an ERB template with the provided text string.

A layout is rendered unless its overriden or the route was declared without one.

To override this from controller actions, you can pass any of the following:



168
169
170
171
172
# File 'lib/doozer/controller.rb', line 168

def render(args={})
  change_layout(args[:layout]) if args[:layout]
  change_view(args[:view]) if args[:view]
  change_view(ERB.new(args[:text])) if args[:text]
end

#render_resultObject

This method is called from the appserver controller handler.



175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/doozer/controller.rb', line 175

def render_result
    layout = @render_args[:layout]
    view = @render_args[:view]
    if layout.kind_of? Symbol # this handles the layout(:none)
      view.result(binding)
    else
      @view[:timestamp] = "<!-- server: #{@port} / rendered: #{Time.now()} / env: #{rack_env} -->"
      @view[:body] = view.result(binding)
      # layout = @layout if layout.nil? # this handles the layout(:some_other_layout) case for formats
      layout.result(binding)
    end
end

Read all the session cookies and store them in the @session instance variable



243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/doozer/controller.rb', line 243

def session_from_cookie
  #split name/value pairs and merge into @session
  if @request.cookies
    if @request.cookies["session"]
      pairs=@request.cookies["session"].split('&')
      pairs.each{|pair| 
        pair = pair.split('=')
        @session[pair[0].to_sym]=CGI::unescape(pair[1])
      }
    end
  end
end

Compile session keys as name=value array which are eventually stored as cookies.



236
237
238
239
240
# File 'lib/doozer/controller.rb', line 236

def session_to_cookie
  #loop over all flash messages and return as name/value array
  out=[]; @session.each { |key, value| out.push("#{key}=#{CGI::escape(value.to_s)}") if not value.nil? }
  return out
end

#write_response_cookies(r) ⇒ Object

Iterates all controller @cookies and writes them to the response



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/doozer/controller.rb', line 280

def write_response_cookies(r)
  @cookies.each { | cookie, values |
    if not values.nil?
      value = []
      path = values.delete(:path) || '/'
      expires = values.delete(:expires) || Time.now + (60 * 60 * 24 * 30)
      values.each { |k, v| 
        value.push("#{k.to_s}=#{CGI::escape(v)}") if not v.nil? 
      }
      value = value.join('&')
    else
      value = ''
      path = ''
      expires = Time.now - 60
    end
    r.set_cookie(cookie.to_s,{:value=>value, :path=>path, :expires=>expires})
  }
  return r
end