spiderfw 0.6.25 → 0.6.26.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/CHANGELOG +15 -0
  2. data/VERSION +1 -1
  3. data/apps/core/auth/controllers/login_controller.rb +2 -0
  4. data/apps/core/auth/controllers/mixins/auth_helper.rb +1 -1
  5. data/apps/core/auth/public/css/login.css +49 -0
  6. data/apps/core/auth/views/login.layout.shtml +14 -0
  7. data/apps/core/auth/views/login.shtml +1 -0
  8. data/apps/core/components/public/js/jquery/plugins/jquery.ui.nestedSortable.js +356 -0
  9. data/apps/core/forms/public/date_time.js +1 -1
  10. data/apps/core/forms/public/select.js +1 -1
  11. data/apps/core/forms/tags/element_row.erb +2 -2
  12. data/apps/core/forms/widgets/form/form.rb +34 -22
  13. data/apps/messenger/_init.rb +1 -0
  14. data/apps/messenger/views/admin/index.shtml +1 -1
  15. data/apps/messenger/views/index.shtml +1 -1
  16. data/blueprints/.DS_Store +0 -0
  17. data/blueprints/home/.DS_Store +0 -0
  18. data/blueprints/install/.DS_Store +0 -0
  19. data/data/keys/spider.rsa +27 -0
  20. data/data/keys/spider.rsa.pub +1 -0
  21. data/lib/spiderfw/app.rb +64 -4
  22. data/lib/spiderfw/autoload.rb +0 -1
  23. data/lib/spiderfw/cmd/commands/app.rb +2 -1
  24. data/lib/spiderfw/controller/controller.rb +189 -90
  25. data/lib/spiderfw/controller/dispatcher.rb +13 -3
  26. data/lib/spiderfw/controller/http_controller.rb +18 -4
  27. data/lib/spiderfw/controller/mixins/http_mixin.rb +37 -10
  28. data/lib/spiderfw/controller/mixins/visual.rb +14 -5
  29. data/lib/spiderfw/http/http.rb +5 -0
  30. data/lib/spiderfw/model/base_model.rb +1 -11
  31. data/lib/spiderfw/model/condition.rb +7 -4
  32. data/lib/spiderfw/model/mappers/mapper.rb +2 -2
  33. data/lib/spiderfw/requires.rb +1 -0
  34. data/lib/spiderfw/setup/app_manager.rb +7 -2
  35. data/lib/spiderfw/setup/setup_task.rb +1 -1
  36. data/lib/spiderfw/setup/spider_setup_wizard.rb +1 -1
  37. data/lib/spiderfw/spider.rb +4 -1
  38. data/lib/spiderfw/templates/layout.rb +8 -3
  39. data/lib/spiderfw/templates/template.rb +2 -1
  40. data/lib/spiderfw/test/rack_tester.rb +10 -0
  41. data/lib/spiderfw/widget/widget_plugin.rb +8 -1
  42. metadata +254 -157
  43. data/lib/spiderfw/model/storage/db/connectors/mysql.rb +0 -16
  44. data/lib/spiderfw/model/storage/db/connectors/mysql2.rb +0 -9
data/lib/spiderfw/app.rb CHANGED
@@ -228,6 +228,12 @@ module Spider
228
228
  end
229
229
  end
230
230
 
231
+ def route_path(action='')
232
+ path = Spider::ControllerMixins::HTTPMixin.reverse_proxy_mapping('/'+@route_url)
233
+ action = action[1..-1] if action[0].chr == '/'
234
+ [path, action].reject{ |p| p.blank? }.join('/')
235
+ end
236
+
231
237
 
232
238
  # Convenience method: since all classes inside the app have an #app method,
233
239
  # the App itself has it too
@@ -237,14 +243,40 @@ module Spider
237
243
  end
238
244
 
239
245
  # Require files inside the App's path
240
- # @param [file1,file2...] files to require
246
+ #
247
+ # Can accept either a list of files to require, relative to the app's path; or, a Hash
248
+ # containing arrays for keys corresponding to folders inside app (e.g. :models, :controllers)
249
+ #
250
+ # If an Hash is provided, will load files in the order :lib, :models, :widgets, :controllers, followed
251
+ # by any additional keys, in the order they are defined in the Hash (under Ruby 1.9.x), or in random order (Ruby 1.8.x)
252
+ # @param [Hash|file1,file2,...] files to require
241
253
  # @return [nil]
242
254
  def req(*list)
243
- list.each do |file|
244
- require File.join(@path, file)
255
+ do_require = lambda{ |f|
256
+ Kernel.require File.join(@path, f)
257
+ }
258
+ if list.first.is_a?(Hash)
259
+ hash = list.first
260
+ load_keys = ([:lib, :models, :widgets, :controllers] + hash.keys).uniq
261
+ load_keys.each do |k|
262
+ if hash[k].is_a?(Array)
263
+ hash[k].each{ |file|
264
+ if k == :widgets
265
+ file = File.join(file, file)
266
+ end
267
+ file = File.join(k.to_s, file)
268
+ do_require.call(file)
269
+ }
270
+ end
271
+ end
272
+ else
273
+ list.each do |file|
274
+ do_require.call(file)
275
+ end
245
276
  end
246
277
  end
247
-
278
+
279
+ alias :app_require :req
248
280
 
249
281
 
250
282
  # Returns the currently installed version of an app
@@ -600,6 +632,34 @@ END_OF_EVAL
600
632
  include TSort
601
633
 
602
634
  end
635
+
636
+ # This module is included Controller and BaseModel, and provides the
637
+ # app method, returning the class' app.
638
+ module AppClass
639
+
640
+ def self.included(klass)
641
+ klass.extend(ClassMethods)
642
+ end
643
+
644
+ # @return [App] The app to which the object's class belongs
645
+ def app
646
+ return self.class.app
647
+ end
648
+
649
+ module ClassMethods
650
+
651
+ # @return [App] The app to which the class belongs
652
+ def app
653
+ return @app if @app
654
+ @app ||= self.parent_module
655
+ while @app && !@app.include?(Spider::App) && @app != Object
656
+ @app = @app.parent_module
657
+ end
658
+ @app = nil if @app && !@app.include?(Spider::App)
659
+ return @app
660
+ end
661
+ end
662
+ end
603
663
 
604
664
  end
605
665
 
@@ -1,6 +1,5 @@
1
1
  module Spider
2
2
  autoload :Logger, "spiderfw/utils/logger"
3
- autoload :App, "spiderfw/app"
4
3
  autoload :Controller, "spiderfw/controller/controller"
5
4
  autoload :Widget, "spiderfw/widget/widget"
6
5
  autoload :PageController, "spiderfw/controller/page_controller"
@@ -190,6 +190,7 @@ module Spider::CommandLine
190
190
  opt.on("--no-clear-cache", _("Don't clear cache"), "-C"){ |c| @no_clear_cache = true }
191
191
  opt.on("--no-restart", _("Don't restart the server after the udpate"), "-R"){ |r| @no_restart = true }
192
192
  opt.on("--branch [BRANCH]", _("Install app from specific branch"), "-b"){ |b| @branch = b }
193
+ opt.on("--no-rollback", _("Don't rollback if update fails")){ |rb| @no_rollback = rb }
193
194
  end
194
195
  update.set_execution_block do |args|
195
196
  $SPIDER_INTERACTIVE = true
@@ -201,7 +202,7 @@ module Spider::CommandLine
201
202
  options = {
202
203
  :no_git => @no_git, :all => @all, :no_deps => @no_deps, :no_optional => @no_optional,
203
204
  :no_gems => @no_gems, :no_optional_gems => @no_optional_gems, :no_activate => @no_activate,
204
- :clear_cache => !@no_clear_cache, :restart => !@no_restart
205
+ :clear_cache => !@no_clear_cache, :restart => !@no_restart, :no_rollback => @no_rollback
205
206
  }
206
207
  options[:url] = @server_url if @server_url
207
208
  options[:branch] = @branch if @branch
@@ -18,6 +18,7 @@ require 'spiderfw/utils/annotations'
18
18
  module Spider
19
19
 
20
20
  class Controller
21
+ include App::AppClass
21
22
  include Dispatcher
22
23
  include Logger
23
24
  include ControllerMixins
@@ -25,60 +26,47 @@ module Spider
25
26
  include Annotations
26
27
 
27
28
  class << self
28
-
29
- def options
30
- @options ||= {}
31
- end
32
-
33
- def option(k, v)
34
- self.option[k] = v
35
- end
36
29
 
37
30
  def default_action
38
31
  'index'
39
32
  end
40
33
 
41
- def app
42
- return @app if @app
43
- @app ||= self.parent_module
44
- while @app && !@app.include?(Spider::App) && @app != Object
45
- @app = @app.parent_module
46
- end
47
- @app = nil if @app && !@app.include?(Spider::App)
48
- return @app
49
- end
50
-
34
+ # @return [String] Path to this controller's templates
51
35
  def template_path
52
36
  return nil unless self.app
53
- return self.app.path+'/views'
37
+ return File.join(self.app.path, '/views')
54
38
  end
55
39
 
40
+ # @return [String] Path to this controller's layouts
56
41
  def layout_path
57
42
  return nil unless self.app
58
- return self.app.path+'/views'
43
+ return File.join(self.app.path, '/views')
59
44
  end
60
45
 
61
46
  # Defines a method that will be called before the controller's before,
62
47
  # if the action matches the given conditions.
63
- # - The first argument, the condition(s), may be a String, a Regexp, a Proc or a Symbol,
64
- # that will be checked against the action, or an Array containing several conditions.
65
- # - The second argument, a Symbol, is the method to be called if the conditions match.
66
- # - The third optional argument, an Hash, may contain :unless => true: in this case,
67
- # the conditions will be inverted, that is, the method will be executed unless the conditions
68
- # match.
69
48
  # Example:
70
- # before('list_', :before_lists)
49
+ # before(/^list_/, :before_lists)
71
50
  # will call the method before_lists if the action starts with 'list_'
51
+ # @param [String|Regexp|Proc|Symbol|Array] conditions what will be checked against the action
52
+ # @param [Symbol] method The method to be called if the conditions match.
53
+ # @param [Hash] params may contain :unless => true: in this case,
54
+ # the conditions will be inverted, that is, the method will
55
+ # be executed unless the conditions match.
56
+ # @return [void]
72
57
  def before(conditions, method, params={})
73
58
  @dispatch_methods ||= {}
74
59
  @dispatch_methods[:before] ||= []
75
60
  @dispatch_methods[:before] << [conditions, method, params]
76
61
  end
77
-
78
- def before_methods
79
- @dispatch_methods && @dispatch_methods[:before] ? @dispatch_methods[:before] : []
80
- end
81
-
62
+
63
+ # Like {Controller.before}, but calls the method unless the conditions match
64
+ # @param [String|Regexp|Proc|Symbol|Array] conditions what will be checked against the action
65
+ # @param [Symbol] method The method to be called if the conditions match.
66
+ # @param [Hash] params may contain :unless => true: in this case,
67
+ # the conditions will be inverted, that is, the method will
68
+ # be executed unless the conditions match.
69
+ # @return [void]
82
70
  def before_unless(condition, method, params={})
83
71
  @dispatch_methods ||= {}
84
72
  @dispatch_methods[:before] ||= []
@@ -86,6 +74,19 @@ module Spider
86
74
  @dispatch_methods[:before] << [condition, method, params]
87
75
  end
88
76
 
77
+ # @return [Array] An array of methods defined with {Controller.before}
78
+ def before_methods
79
+ @dispatch_methods && @dispatch_methods[:before] ? @dispatch_methods[:before] : []
80
+ end
81
+
82
+ # Registers a list of methods as controller actions, that is, methods that can
83
+ # be dispatched to.
84
+ #
85
+ # This method is not usually called directly; using the __.action annotation,
86
+ # or one of the format annotations (__.html, __.xml, __.json, __.text), will
87
+ # make a method a controller action.
88
+ # @param [*Symbol] A list of methods
89
+ # @return [Array] All defined controller actions
89
90
  def controller_actions(*methods)
90
91
  if (methods.length > 0)
91
92
  @controller_actions ||= []
@@ -93,7 +94,15 @@ module Spider
93
94
  end
94
95
  @controller_actions
95
96
  end
97
+
98
+ def controller_action(method, params)
99
+ @controller_actions ||= []
100
+ @controller_actions << method
101
+ @controller_action_params ||= {}
102
+ @controller_action_params[method] = params
103
+ end
96
104
 
105
+ # @return [bool] true if the method is a controller action
97
106
  def controller_action?(method)
98
107
  return false unless self.method_defined?(method)
99
108
  return true if default_action && method == default_action.to_sym
@@ -108,35 +117,75 @@ module Spider
108
117
  end
109
118
  end
110
119
 
120
+ # Finds a resource in the context of the controller's app
121
+ # See {Spider.find_resource}
122
+ # @param [Symbol] resource_type
123
+ # @param [String] path
124
+ # @param [String] cur_path Current path: if set, will be used to resolve relative paths
125
+ # @return [Resource]
111
126
  def find_resource(type, name, cur_path=nil)
112
127
  Spider.find_resource(type, name, cur_path, self)
113
128
  end
114
129
 
130
+ # Returns the path of a resource, or nil if none is found
131
+ # See {Controller.find_resource}
132
+ # @param [Symbol] resource_type
133
+ # @param [String] path
134
+ # @param [String] cur_path Current path: if set, will be used to resolve relative paths
135
+ # @return [Resource]
115
136
  def find_resource_path(type, name, cur_path=nil)
116
137
  res = Spider.find_resource(type, name, cur_path, self)
117
138
  return res ? res.path : nil
118
139
  end
119
140
 
120
- # Returns the canonical url for this controller
121
- def url(action=nil)
141
+ # @param [String] action Additional action to get path for
142
+ # @return [String] The canonical URL path for this controller
143
+ def route_path(action=nil)
122
144
  u = @default_route || ''
123
145
  u += "/#{action}" if action
124
146
  if @default_dispatcher && @default_dispatcher != self
125
- u = @default_dispatcher.url + '/' + u
147
+ u = @default_dispatcher.route_path(u)
126
148
  elsif self.app
127
- u = self.app.url + '/' + u
149
+ u = self.app.route_path(u)
128
150
  end
129
151
  u
130
152
  end
153
+
154
+ # Returns the full URL for the Controller
155
+ # The Controller's implementation returns the route_path.
156
+ #
157
+ # However, the HTTPMixin will override this method to return a full http url;
158
+ # other mixins can override the method in different ways.
159
+ # @param [String] action Additional action to get path for
160
+ # @return [String] The canonical URL for this controller
161
+ def url(action=nil)
162
+ route_path(action)
163
+ end
164
+ alias :route_url :url
131
165
 
132
166
 
133
167
  end
134
168
 
135
- define_annotation(:action) { |k, m| k.controller_actions(m) }
169
+ define_annotation(:action) { |k, m, params| k.controller_action(m, params) }
136
170
 
137
- attr_reader :request, :response, :executed_method, :scene
138
- attr_accessor :dispatch_action, :is_target
171
+ # @return [Spider::Request]
172
+ attr_reader :request
173
+ # @return [Spider::Response]
174
+ attr_reader :response
175
+ # @return [Symbol] The method currently set to be executed, if any
176
+ attr_reader :executed_method
177
+ # @return [Scene]
178
+ attr_reader :scene
179
+ # @return [String] Action used to reach this controller in the dispatch chain
180
+ attr_accessor :dispatch_action
181
+ # @return [bool] True if the controller is the target of the current action
182
+ attr_accessor :is_target
139
183
 
184
+ # Constructor. Note: you can use the {Controller#init} method for custom
185
+ # initialization, instead of overrideing this method
186
+ # @param [Spider::Request] request
187
+ # @param [Spider::Response] response
188
+ # @param [scene]
140
189
  def initialize(request, response, scene=nil)
141
190
  @request = request
142
191
  @response = response
@@ -144,19 +193,20 @@ module Spider
144
193
  @dispatch_path = ''
145
194
  @is_target = true
146
195
  init
147
- #@parent = parent
148
196
  end
149
197
 
150
198
  # Override this for controller initialization
199
+ # @return [void]
151
200
  def init
152
-
153
201
  end
154
202
 
203
+ # @return [String]
155
204
  def inspect
156
205
  self.class.to_s
157
206
  end
158
207
 
159
- def call_path
208
+ # @return [String] The actual action path used to reach this Controller
209
+ def request_path
160
210
  act = @dispatch_action || ''
161
211
  if (@dispatch_previous)
162
212
  prev = @dispatch_previous.call_path
@@ -164,16 +214,15 @@ module Spider
164
214
  end
165
215
  return ('/'+act).gsub(/\/+/, '/').sub(/\/$/, '')
166
216
  end
217
+ alias :call_path :request_path
167
218
 
168
- def request_path
169
- call_path
170
- end
171
-
219
+ # Returns the method to call on the controller given an action, and the arguments
220
+ # that should be passed to it.
221
+ # @param [String] action
222
+ # @return [Array] A two elements array, containing the method, and additional arguments
172
223
  def get_action_method(action)
173
224
  method = nil
174
225
  additional_arguments = nil
175
- # method = action.empty? ? self.class.default_action : action
176
- # method = method.split('/', 2)[0]
177
226
  if (action =~ /^([^:]+)(:.+)$/)
178
227
  method = $1
179
228
  elsif (action =~ /^([^\/]+)\/(.+)$/) # methods followed by a slash
@@ -191,16 +240,26 @@ module Spider
191
240
 
192
241
  # Returns true if this controller is the final target for the current action, that is, if it does not
193
242
  # dispatch to any route
243
+ # @return [bool] True if the controller is the final target
194
244
  def action_target?
195
- !@dispatch_next[@call_path] || @dispatch_next[@call_path].dest == self
245
+ !@dispatch_next[@call_path] || @dispatch_next[@call_path].dest == self \
246
+ || @dispatch_next[@call_path].dest == self.class
196
247
  end
197
248
 
198
- # Returns false if the target of the call is a widget, true otherwise
249
+ # @return [bool] false if the target of the call is a widget, true otherwise
199
250
  def is_target?
200
251
  @is_target
201
252
  end
202
253
 
203
254
 
255
+ # The main controller's execution method. The Controller will dispatch
256
+ # to another controller if a route is set; otherwise, it will call the
257
+ # method that should be executed according to action.
258
+ #
259
+ # This method can be overridden in subclasses, but remember to call super,
260
+ # or the dispatch chain will stop!
261
+ # @param [String] action The current action
262
+ # @param [*Object] arguments Additional action arguments
204
263
  def execute(action='', *arguments)
205
264
  return if @__done
206
265
  debug("Controller #{self} executing #{action} with arguments #{arguments}")
@@ -218,7 +277,7 @@ module Spider
218
277
  if @executed_method
219
278
  meth = self.method(@executed_method)
220
279
  args = arguments + @executed_method_arguments
221
- @controller_action = args[0]
280
+ @current_action = action
222
281
  arity = meth.arity
223
282
  unless arity == -1
224
283
  arity = (-arity + 1) if arity < 0
@@ -234,6 +293,9 @@ module Spider
234
293
  end
235
294
  end
236
295
 
296
+ # Helper method, that calls and propagates #before
297
+ # @param [String] action The current action
298
+ # @param [*Object] arguments Additional action arguments
237
299
  def call_before(action='', *arguments)
238
300
  return if respond_to?(:serving_static?) && self.serving_static?
239
301
  @call_path = action
@@ -246,11 +308,21 @@ module Spider
246
308
  end
247
309
  end
248
310
  end
249
-
311
+
312
+ # This method can be implemented by Controllers, and will be called
313
+ # on the controller chain before the execute method.
314
+ #
315
+ # This method is usually reserved for preprocessing that does not
316
+ # output to the browser, to allow other controllers in chain to set response
317
+ # headers.
318
+ # @param [String] action The current action
319
+ # @param [*Object] arguments Additional action arguments
250
320
  def before(action='', *arguments)
251
321
  end
252
322
 
253
-
323
+ # Helper method, that calls and propagates #after
324
+ # @param [String] action The current action
325
+ # @param [*Object] arguments Additional action arguments
254
326
  def call_after(action='', *arguments)
255
327
  return if respond_to?(:serving_static?) && self.serving_static?
256
328
  after(action, *arguments)
@@ -260,43 +332,63 @@ module Spider
260
332
  do_dispatch(:call_after, action, *arguments)
261
333
  end
262
334
  end
263
- # begin
264
- # run_chain(:after)
265
- # #dispatch(:after, action, params)
266
- # rescue => exc
267
- # try_rescue(exc)
268
- # end
269
335
  end
270
336
 
337
+ # This method can be implemented by Controllers, and will be called
338
+ # on the controller chain after the execute method.
339
+ #
340
+ # If the webserver supports it, this method will be called after the response
341
+ # has been returned to the browser; so, it's suitable for post processing.
342
+ # If you aren't using a threaded web server, though, keep in mind that the
343
+ # process won't be available to service other requests.
344
+ # @param [String] action The current action
345
+ # @param [*Object] arguments Additional action arguments
271
346
  def after(action='', *arguments)
272
347
  end
273
348
 
349
+ # @return [bool] True if the controller is done, and should not continue dispatching.
274
350
  def done?
275
351
  @__done
276
352
  end
277
353
 
354
+ # Stops the execution of the controller chain
355
+ # @return [void]
278
356
  def done
279
357
  self.done = true
280
358
  throw :done
281
359
  end
282
360
 
361
+ # Sets the controller chain's "done" state
362
+ # @param [bool] val
363
+ # @return [void]
283
364
  def done=(val)
284
365
  @__done = val
285
366
  @dispatch_previous.done = val if @dispatch_previous
286
367
  end
287
368
 
369
+ # Checks if an action responds to given route conditions. Is called by
370
+ # {Dispatcher#do_dispatch}.
371
+ # The default implementation calls Controller.check_action, which in turn is mixed in
372
+ # from {Dispatcher::ClassMethods#check_action}
373
+ # @param [String] action
374
+ # @param [Array] c An array of route conditions
375
+ # @return [bool]
288
376
  def check_action(action, c)
289
377
  self.class.check_action(action, c)
290
378
  end
291
379
 
380
+ # Returns a new Scene instance for use in the controller.
381
+ # @param [Hash] scene Hash to construct the scene from
382
+ # @return [Scene]
292
383
  def get_scene(scene=nil)
293
384
  scene = Scene.new(scene) if scene.class == Hash
294
385
  scene ||= Scene.new
295
- # debugger
296
- # scene.extend(SceneMethods)
297
386
  return scene
298
387
  end
299
388
 
389
+ # Sets controller information on a scene
390
+ # @param [Scene] scene
391
+ # @return [Scene]
300
392
  def prepare_scene(scene)
301
393
  req_path = @request.path
302
394
  req_path += 'index' if !req_path.blank? && req_path[-1].chr == '/'
@@ -312,19 +404,17 @@ module Spider
312
404
  return scene
313
405
  end
314
406
 
315
- def get_route(*args)
316
- route = super
317
- return route unless route
318
- action = route.path.split('/').first
319
- action_method, action_params = get_action_method(action)
320
- if route.nil_route && !action.blank? && self.respond_to?(action_method)
321
- route.action = action
322
- end
323
- route
407
+ # See {Controller.controller_action?}
408
+ # @return [bool] True if the method is a controller action for the class
409
+ def controller_action?(method)
410
+ self.class.controller_action?(method)
324
411
  end
325
412
 
326
413
  protected
327
414
 
415
+ # Instantiates an object dispatched by a route
416
+ # @param [Route]
417
+ # @return [Controller]
328
418
  def dispatched_object(route)
329
419
  klass = route.dest
330
420
  if klass.class != Class
@@ -332,6 +422,9 @@ module Spider
332
422
  set_executed_method(route.action)
333
423
  end
334
424
  return klass
425
+ elsif klass == self.class
426
+ self.set_action(route.action)
427
+ return self
335
428
  end
336
429
  obj = klass.new(@request, @response, @scene)
337
430
  obj.dispatch_action = route.matched || ''
@@ -341,46 +434,52 @@ module Spider
341
434
  return obj
342
435
  end
343
436
 
344
- def controller_action?(method)
345
- self.class.controller_action?(method)
346
- end
347
-
437
+ # Given an action, sets the executed method unless it can be dispatched
438
+ # @param [String] action
439
+ # @return [Symbol|nil] The executed method, if it was set, or nil
348
440
  def set_action(action)
349
441
  @executed_method = nil
350
442
  @executed_method_arguments = nil
351
443
  if !can_dispatch?(:execute, action)
352
- set_executed_method(action)
444
+ return set_executed_method(action)
353
445
  end
446
+ nil
354
447
  end
355
448
 
449
+ # Given an action, sets executed_method and executed_method_arguments
450
+ # @param [String] action
451
+ # @return [Symbol] The executed_method
356
452
  def set_executed_method(action)
357
453
  method, additional_arguments = get_action_method(action)
358
- if (method && controller_action?(method))
454
+ if method && controller_action?(method)
359
455
  @executed_method = method.to_sym
360
456
  @executed_method_arguments = additional_arguments || []
361
457
  end
362
458
  return @executed_method
363
459
  end
364
-
365
460
 
461
+ # This method can be overrided by subclasses, to provide custom handling of
462
+ # exceptions
463
+ # @param [Exception]
464
+ # @return [void]
366
465
  def try_rescue(exc)
367
466
  raise exc
368
467
  end
369
-
370
-
468
+
371
469
  private
372
-
373
- def pass
374
- action = @call_path
375
- return false unless can_dispatch?(:execute, action)
376
- #debug("CAN DISPATCH #{action}")
377
- do_dispatch(:execute, action)
378
- return true
379
- end
380
-
381
- module SceneMethods
382
- end
383
470
 
471
+ # Overrides {Dispatcher#get_route}, setting the action for nil routes
472
+ # @param [String] path
473
+ def get_route(*args)
474
+ route = super
475
+ return route unless route
476
+ action = route.path.split('/').first
477
+ action_method, action_params = get_action_method(action)
478
+ if route.nil_route && !action.blank? && self.respond_to?(action_method)
479
+ route.action = action
480
+ end
481
+ route
482
+ end
384
483
 
385
484
  end
386
485
 
@@ -62,7 +62,8 @@ module Spider
62
62
  return nil if obj == self && route_action == action # short circuit
63
63
  meth_action = route_action.length > 0 ? route_action : obj.class.default_action
64
64
  begin
65
- if (obj.class.dispatch_methods && obj.class.dispatch_methods[method])
65
+ # Apply dispatch methods (see {Controller.before})
66
+ if obj.class.dispatch_methods && obj.class.dispatch_methods[method]
66
67
  obj.class.dispatch_methods[method].each do |dm|
67
68
  conditions, d_method, params = dm
68
69
  test = check_action(route_action, conditions)
@@ -71,6 +72,7 @@ module Spider
71
72
  end
72
73
  end
73
74
  res = obj.send(method, route_action, *(new_arguments))
75
+ # Call, for example, before_my_method
74
76
  unless meth_action.empty?
75
77
  meth_action = meth_action[0..-2] if meth_action[-1].chr == '/'
76
78
  meth_action = meth_action.split('/', 2)[0]
@@ -131,6 +133,7 @@ module Spider
131
133
  try, dest, options = route
132
134
  action = nil
133
135
  nil_route = false
136
+ next if options[:http_method] && @request.http_method != options[:http_method]
134
137
  case try
135
138
  when true, nil
136
139
  action = path
@@ -157,8 +160,8 @@ module Spider
157
160
  end
158
161
  when Proc
159
162
  res = try.call(path, self)
160
- if (res)
161
- if (res.is_a?(Array))
163
+ if res
164
+ if res.is_a?(Array)
162
165
  action = res[0]
163
166
  params = res[1]
164
167
  matched = res[1]
@@ -166,6 +169,13 @@ module Spider
166
169
  action = res
167
170
  end
168
171
  end
172
+ when Symbol
173
+ if Spider::HTTP::METHODS.include?(try)
174
+ if @request.http_method == try
175
+ action = path
176
+ matched = nil
177
+ end
178
+ end
169
179
  end
170
180
  if action
171
181
  action = action[1..-1] if action[0] && action[0].chr == '/'