Class: Spider::Controller

Inherits:
Object show all
Includes:
Annotations, App::AppClass, ControllerMixins, Dispatcher, Helpers, Logger
Defined in:
lib/spiderfw/controller/controller.rb,
lib/spiderfw/controller/controller_exceptions.rb

Defined Under Namespace

Classes: BadRequest, ControllerError, Forbidden, Maintenance, NotFound

Instance Attribute Summary collapse

Attributes included from Dispatcher

#dispatch_previous

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Annotations

included

Methods included from Logger

add, check_request_level, close, close_all, datetime_format, datetime_format=, #debug, debug, debug?, #debug?, enquire_loggers, #error, error, #error?, error?, fatal, #fatal, fatal?, #fatal?, info, #info, info?, #info?, #log, log, method_missing, open, reopen, request_level, send_to_loggers, set_request_level, unknown, #unknown, warn, #warn, warn?, #warn?

Methods included from Dispatcher

#add_chain_item, #can_dispatch?, #dispatch, #dispatch_chain, #dispatch_next, #dispatcher_get_route, #do_dispatch, included, #route, #routes, #run_chain

Methods included from App::AppClass

#app, included

Constructor Details

#initialize(request, response, scene = nil) ⇒ Controller

Constructor. Note: you can use the #init method for custom initialization, instead of overrideing this method

Parameters:



189
190
191
192
193
194
195
196
# File 'lib/spiderfw/controller/controller.rb', line 189

def initialize(request, response, scene=nil)
    @request = request
    @response = response
    @scene = scene || get_scene
    @dispatch_path = ''
    @is_target = true
    init
end

Instance Attribute Details

#dispatch_actionString

Returns Action used to reach this controller in the dispatch chain.

Returns:

  • (String)

    Action used to reach this controller in the dispatch chain



180
181
182
# File 'lib/spiderfw/controller/controller.rb', line 180

def dispatch_action
  @dispatch_action
end

#executed_methodSymbol (readonly)

Returns The method currently set to be executed, if any.

Returns:

  • (Symbol)

    The method currently set to be executed, if any



176
177
178
# File 'lib/spiderfw/controller/controller.rb', line 176

def executed_method
  @executed_method
end

#is_targetbool

Returns True if the controller is the target of the current action.

Returns:

  • (bool)

    True if the controller is the target of the current action



182
183
184
# File 'lib/spiderfw/controller/controller.rb', line 182

def is_target
  @is_target
end

#requestSpider::Request (readonly)

Returns:



172
173
174
# File 'lib/spiderfw/controller/controller.rb', line 172

def request
  @request
end

#responseSpider::Response (readonly)

Returns:



174
175
176
# File 'lib/spiderfw/controller/controller.rb', line 174

def response
  @response
end

#sceneScene (readonly)

Returns:



178
179
180
# File 'lib/spiderfw/controller/controller.rb', line 178

def scene
  @scene
end

Class Method Details

.before(conditions, method, params = {}) ⇒ void

This method returns an undefined value.

Defines a method that will be called before the controller’s before, if the action matches the given conditions. Example:

before(/^list_/, :before_lists)

will call the method before_lists if the action starts with ‘list_’

Parameters:

  • conditions (String|Regexp|Proc|Symbol|Array)

    what will be checked against the action

  • method (Symbol)

    The method to be called if the conditions match.

  • params (Hash) (defaults to: {})

    may contain :unless => true: in this case, the conditions will be inverted, that is, the method will be executed unless the conditions match.



57
58
59
60
61
# File 'lib/spiderfw/controller/controller.rb', line 57

def before(conditions, method, params={})
    @dispatch_methods ||= {}
    @dispatch_methods[:before] ||= []
    @dispatch_methods[:before] << [conditions, method, params]
end

.before_methodsArray

Returns An array of methods defined with before.

Returns:

  • (Array)

    An array of methods defined with before



78
79
80
# File 'lib/spiderfw/controller/controller.rb', line 78

def before_methods
    @dispatch_methods && @dispatch_methods[:before] ? @dispatch_methods[:before] : []
end

.before_unless(condition, method, params = {}) ⇒ void

This method returns an undefined value.

Like before, but calls the method unless the conditions match

Parameters:

  • conditions (String|Regexp|Proc|Symbol|Array)

    what will be checked against the action

  • method (Symbol)

    The method to be called if the conditions match.

  • params (Hash) (defaults to: {})

    may contain :unless => true: in this case, the conditions will be inverted, that is, the method will be executed unless the conditions match.



70
71
72
73
74
75
# File 'lib/spiderfw/controller/controller.rb', line 70

def before_unless(condition, method, params={})
    @dispatch_methods ||= {}
    @dispatch_methods[:before] ||= []
    params[:unless] = true
    @dispatch_methods[:before] << [condition, method, params]
end

.controller_action(method, params) ⇒ Object



98
99
100
101
102
103
# File 'lib/spiderfw/controller/controller.rb', line 98

def controller_action(method, params)
    @controller_actions ||= []
    @controller_actions << method
    @controller_action_params ||= {}
    @controller_action_params[method] = params
end

.controller_action?(method) ⇒ bool

Returns true if the method is a controller action.

Returns:

  • (bool)

    true if the method is a controller action



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/spiderfw/controller/controller.rb', line 106

def controller_action?(method)
    return false unless self.method_defined?(method)
    return true if default_action && method == default_action.to_sym
    if @controller_actions
        res = @controller_actions.include?(method)
        if (!res)
            Spider.logger.info("Method #{method} is not a controller action for #{self}")
        end
        return res
    else
        return true
    end
end

.controller_actions(*methods) ⇒ Array

Registers a list of methods as controller actions, that is, methods that can be dispatched to.

This method is not usually called directly; using the __.action annotation, or one of the format annotations (__.html, __.xml, __.json, __.text), will make a method a controller action.

Parameters:

  • A (*Symbol)

    list of methods

Returns:

  • (Array)

    All defined controller actions



90
91
92
93
94
95
96
# File 'lib/spiderfw/controller/controller.rb', line 90

def controller_actions(*methods)
    if (methods.length > 0)
        @controller_actions ||= []
        @controller_actions += methods
    end
    @controller_actions
end

.default_actionObject



30
31
32
# File 'lib/spiderfw/controller/controller.rb', line 30

def default_action
    'index'
end

.find_resource(type, name, cur_path = nil) ⇒ Resource

Finds a resource in the context of the controller’s app See Spider.find_resource

Parameters:

  • resource_type (Symbol)
  • path (String)
  • cur_path (String) (defaults to: nil)

    Current path: if set, will be used to resolve relative paths

Returns:



126
127
128
# File 'lib/spiderfw/controller/controller.rb', line 126

def find_resource(type, name, cur_path=nil)
    Spider.find_resource(type, name, cur_path, self)
end

.find_resource_path(type, name, cur_path = nil) ⇒ Resource

Returns the path of a resource, or nil if none is found See find_resource

Parameters:

  • resource_type (Symbol)
  • path (String)
  • cur_path (String) (defaults to: nil)

    Current path: if set, will be used to resolve relative paths

Returns:



136
137
138
139
# File 'lib/spiderfw/controller/controller.rb', line 136

def find_resource_path(type, name, cur_path=nil)
    res = Spider.find_resource(type, name, cur_path, self)
    return res ? res.path : nil
end

.http_s_url(action = nil) ⇒ Object

If the site supports SSL, returns the #https_url; otherwise, the #http_url



255
256
257
# File 'lib/spiderfw/controller/controller.rb', line 255

def self.http_s_url(action=nil)
    (Spider.site.blank? ? "" : Spider.site.http_s_url) + route_path(action)
end

.layout_pathString

Returns Path to this controller’s layouts.

Returns:

  • (String)

    Path to this controller’s layouts



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

def layout_path
    return nil unless self.app
    return File.join(self.app.path, '/views')
end

.route_path(action = nil) ⇒ String

Returns The canonical URL path for this controller.

Parameters:

  • action (String) (defaults to: nil)

    Additional action to get path for

Returns:

  • (String)

    The canonical URL path for this controller



143
144
145
146
147
148
149
150
151
152
# File 'lib/spiderfw/controller/controller.rb', line 143

def route_path(action=nil)
    u = @default_route || ''
    u += "/#{action}" if action
    if @default_dispatcher && @default_dispatcher != self
        u = @default_dispatcher.route_path(u)
    elsif self.app
        u = self.app.route_path(u)
    end
    u
end

.template_pathString

Returns Path to this controller’s templates.

Returns:

  • (String)

    Path to this controller’s templates



35
36
37
38
# File 'lib/spiderfw/controller/controller.rb', line 35

def template_path
    return nil unless self.app
    return File.join(self.app.path, '/views')
end

.url(action = nil) ⇒ String Also known as: route_url

Returns the full URL for the Controller The Controller’s implementation returns the route_path.

However, the HTTPMixin will override this method to return a full http url; other mixins can override the method in different ways.

Parameters:

  • action (String) (defaults to: nil)

    Additional action to get path for

Returns:

  • (String)

    The canonical URL for this controller



161
162
163
# File 'lib/spiderfw/controller/controller.rb', line 161

def url(action=nil)
    route_path(action)
end

Instance Method Details

#action_target?bool

Returns true if this controller is the final target for the current action, that is, if it does not dispatch to any route

Returns:

  • (bool)

    True if the controller is the final target



244
245
246
247
# File 'lib/spiderfw/controller/controller.rb', line 244

def action_target?
    !@dispatch_next[@call_path] || @dispatch_next[@call_path].dest == self \
    || @dispatch_next[@call_path].dest == self.class
end

#after(action = '', *arguments) ⇒ Object

This method can be implemented by Controllers, and will be called on the controller chain after the execute method.

If the webserver supports it, this method will be called after the response has been returned to the browser; so, it’s suitable for post processing. If you aren’t using a threaded web server, though, keep in mind that the process won’t be available to service other requests.

Parameters:

  • action (String) (defaults to: '')

    The current action

  • arguments (*Object)

    Additional action arguments



350
351
# File 'lib/spiderfw/controller/controller.rb', line 350

def after(action='', *arguments)
end

#before(action = '', *arguments) ⇒ Object

This method can be implemented by Controllers, and will be called on the controller chain before the execute method.

This method is usually reserved for preprocessing that does not output to the browser, to allow other controllers in chain to set response headers.

Parameters:

  • action (String) (defaults to: '')

    The current action

  • arguments (*Object)

    Additional action arguments



324
325
# File 'lib/spiderfw/controller/controller.rb', line 324

def before(action='', *arguments)
end

#call_after(action = '', *arguments) ⇒ Object

Helper method, that calls and propagates #after

Parameters:

  • action (String) (defaults to: '')

    The current action

  • arguments (*Object)

    Additional action arguments



330
331
332
333
334
335
336
337
338
339
# File 'lib/spiderfw/controller/controller.rb', line 330

def call_after(action='', *arguments)
    return if respond_to?(:serving_static?) && self.serving_static?
    after(action, *arguments)
    catch(:done) do
        d_next = dispatch_next(action)
        unless d_next && d_next.obj == self
            do_dispatch(:call_after, action, *arguments)
        end
    end
end

#call_before(action = '', *arguments) ⇒ Object

Helper method, that calls and propagates #before

Parameters:

  • action (String) (defaults to: '')

    The current action

  • arguments (*Object)

    Additional action arguments



303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/spiderfw/controller/controller.rb', line 303

def call_before(action='', *arguments)
    return if respond_to?(:serving_static?) && self.serving_static?
    @call_path = action
    before(action, *arguments)
    catch(:done) do
        #debug("#{self} before")
        d_next = dispatch_next(action)
        unless d_next && d_next.obj == self
            do_dispatch(:call_before, action, *arguments)
        end
    end
end

#check_action(action, c) ⇒ bool

Checks if an action responds to given route conditions. Is called by Dispatcher#do_dispatch. The default implementation calls Controller.check_action, which in turn is mixed in from Dispatcher::ClassMethods#check_action

Parameters:

  • action (String)
  • c (Array)

    An array of route conditions

Returns:

  • (bool)


380
381
382
# File 'lib/spiderfw/controller/controller.rb', line 380

def check_action(action, c)
    self.class.check_action(action, c)
end

#controller_action?(method) ⇒ bool

Returns:

  • (bool)

    True if the method is a controller action for the class



413
414
415
# File 'lib/spiderfw/controller/controller.rb', line 413

def controller_action?(method)
    self.class.controller_action?(method)
end

#donevoid

This method returns an undefined value.

Stops the execution of the controller chain



360
361
362
363
# File 'lib/spiderfw/controller/controller.rb', line 360

def done
    self.done = true
    throw :done
end

#done=(val) ⇒ void

This method returns an undefined value.

Sets the controller chain’s “done” state

Parameters:

  • val (bool)


368
369
370
371
# File 'lib/spiderfw/controller/controller.rb', line 368

def done=(val)
    @__done = val
    @dispatch_previous.done = val if @dispatch_previous
end

#done?bool

Returns True if the controller is done, and should not continue dispatching.

Returns:

  • (bool)

    True if the controller is done, and should not continue dispatching.



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

def done?
    @__done
end

#execute(action = '', *arguments) ⇒ Object

The main controller’s execution method. The Controller will dispatch to another controller if a route is set; otherwise, it will call the method that should be executed according to action.

This method can be overridden in subclasses, but remember to call super, or the dispatch chain will stop!

Parameters:

  • action (String) (defaults to: '')

    The current action

  • arguments (*Object)

    Additional action arguments



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/spiderfw/controller/controller.rb', line 267

def execute(action='', *arguments)
    return if @__done
    debug("Controller #{self} executing #{action} with arguments #{arguments}")
    catch(:done) do
        if can_dispatch?(:execute, action)
            d_next = dispatch_next(action)
            #run_chain(:execute, action, *arguments)
            #  shortcut route to self
            return do_dispatch(:execute, action) if d_next.dest != self 
            arguments = d_next.params
        end
        if d_next && d_next.dest == self
            set_executed_method(d_next.action)
        end
        if @executed_method
            meth = self.method(@executed_method)
            args = arguments + @executed_method_arguments
            @current_action = action
            arity = meth.arity
            unless arity == -1
                arity = (-arity + 1) if arity < 0
                args = arity == 0 ? [] : args[0..(arity-1)]
                args = [nil] if meth.arity == 1 && args.empty?
            end
            Spider.logger.info("Executing: #{self.class.name}##{@executed_method}.#{@request.format}")
            spider_main_controller_send = true
            send(@executed_method, *args)
        else
            raise NotFound.new(action)
        end
    end
end

#get_action_method(action) ⇒ Array

Returns the method to call on the controller given an action, and the arguments that should be passed to it.

Parameters:

Returns:

  • (Array)

    A two elements array, containing the method, and additional arguments



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/spiderfw/controller/controller.rb', line 223

def get_action_method(action)
    method = nil
    additional_arguments = nil
    if (action =~ /^([^:]+)(:.+)$/)
        method = $1
    elsif (action =~ /^([^\/]+)\/(.+)$/) # methods followed by a slash
        method = $1
        additional_arguments = [$2]
    else
        method = action
    end
    method = method[0..-2] if !method.blank? && method[-1].chr == '/'
    method, rest = method.split('.', 2) if method
    method = self.class.default_action if !method || method.empty?
    return nil if method.empty?
    return [method.to_sym, additional_arguments]
end

#get_scene(scene = nil) ⇒ Scene

Returns a new Scene instance for use in the controller.

Parameters:

  • scene (Hash) (defaults to: nil)

    Hash to construct the scene from

Returns:



387
388
389
390
391
# File 'lib/spiderfw/controller/controller.rb', line 387

def get_scene(scene=nil)
    scene = Scene.new(scene) if scene.class == Hash
    scene ||= Scene.new
    return scene
end

#initvoid

This method returns an undefined value.

Override this for controller initialization



200
201
# File 'lib/spiderfw/controller/controller.rb', line 200

def init
end

#inspectString

Returns:



204
205
206
# File 'lib/spiderfw/controller/controller.rb', line 204

def inspect
    self.class.to_s
end

#is_target?bool

Returns false if the target of the call is a widget, true otherwise.

Returns:

  • (bool)

    false if the target of the call is a widget, true otherwise



250
251
252
# File 'lib/spiderfw/controller/controller.rb', line 250

def is_target?
    @is_target
end

#prepare_scene(scene) ⇒ Scene

Sets controller information on a scene

Parameters:

Returns:



396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/spiderfw/controller/controller.rb', line 396

def prepare_scene(scene)
    req_path = @request.path
    req_path += 'index' if !req_path.blank? && req_path[-1].chr == '/'
    scene.request = {
        :path => @request.path,
        :page_path => req_path
    }
    scene.controller = {
        :request_path => request_path,
        :class => self.class
    }
    scene.content = {}
    return scene
end

#request_pathString Also known as: call_path

Returns The actual action path used to reach this Controller.

Returns:

  • (String)

    The actual action path used to reach this Controller



209
210
211
212
213
214
215
216
# File 'lib/spiderfw/controller/controller.rb', line 209

def request_path
    act = @dispatch_action || ''
    if (@dispatch_previous)
        prev = @dispatch_previous.call_path 
        act = prev+'/'+act unless prev.empty?
    end
    return ('/'+act).gsub(/\/+/, '/').sub(/\/$/, '')
end