padrino-core 0.9.24 → 0.9.25
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/padrino-core/application.rb +11 -22
- data/lib/padrino-core/application/rendering.rb +13 -4
- data/lib/padrino-core/application/routing.rb +159 -124
- data/lib/padrino-core/cli/base.rb +1 -0
- data/lib/padrino-core/cli/console.rb +1 -1
- data/lib/padrino-core/cli/rake.rb +5 -0
- data/lib/padrino-core/loader.rb +3 -6
- data/lib/padrino-core/logger.rb +13 -5
- data/lib/padrino-core/mounter.rb +35 -36
- data/lib/padrino-core/reloader.rb +4 -4
- data/lib/padrino-core/support_lite.rb +1 -1
- data/lib/padrino-core/version.rb +1 -1
- data/padrino-core.gemspec +3 -2
- data/test/fixtures/apps/simple.rb +1 -1
- data/test/test_logger.rb +18 -1
- data/test/test_mounter.rb +9 -4
- data/test/test_reloader_complex.rb +20 -18
- data/test/test_reloader_simple.rb +2 -1
- data/test/test_router.rb +2 -2
- data/test/test_routing.rb +70 -25
- metadata +35 -19
@@ -63,7 +63,7 @@ module Padrino
|
|
63
63
|
# MyApp.reset_routes!
|
64
64
|
#
|
65
65
|
def reset_routes!
|
66
|
-
|
66
|
+
reset_router!
|
67
67
|
default_routes!
|
68
68
|
end
|
69
69
|
|
@@ -84,7 +84,6 @@ module Padrino
|
|
84
84
|
#
|
85
85
|
def setup_application!
|
86
86
|
return if @_configured
|
87
|
-
self.calculate_paths
|
88
87
|
self.register_initializers
|
89
88
|
self.require_load_paths
|
90
89
|
self.disable :logging # We need do that as default because Sinatra use commonlogger.
|
@@ -134,7 +133,9 @@ module Padrino
|
|
134
133
|
set :padrino_logging, true
|
135
134
|
set :method_override, true
|
136
135
|
set :sessions, false
|
137
|
-
set :public, Proc.new { Padrino.root('public',
|
136
|
+
set :public, Proc.new { Padrino.root('public', uri_root) }
|
137
|
+
set :views, Proc.new { File.join(root, "views") }
|
138
|
+
set :images_path, Proc.new { File.join(public, "images") }
|
138
139
|
# Padrino specific
|
139
140
|
set :uri_root, "/"
|
140
141
|
set :reload, Proc.new { development? }
|
@@ -184,23 +185,13 @@ module Padrino
|
|
184
185
|
end
|
185
186
|
end
|
186
187
|
|
187
|
-
##
|
188
|
-
# Calculates any required paths after app_file and root have been properly configured
|
189
|
-
# Executes as part of the setup_application! method
|
190
|
-
#
|
191
|
-
def calculate_paths
|
192
|
-
raise ApplicationSetupError.new("Please define 'app_file' option for #{self.name} app!") unless self.app_file
|
193
|
-
set :views, find_view_path if find_view_path
|
194
|
-
set :images_path, File.join(self.public, "/images") unless self.respond_to?(:images_path)
|
195
|
-
end
|
196
|
-
|
197
188
|
##
|
198
189
|
# Requires the Padrino middleware
|
199
190
|
#
|
200
191
|
def register_initializers
|
201
|
-
use Padrino::Logger::Rack
|
202
|
-
use Padrino::Reloader::Rack
|
203
|
-
use Rack::Flash
|
192
|
+
use Padrino::Logger::Rack, uri_root if Padrino.logger && (Padrino.logger.level == 0 && padrino_logging?)
|
193
|
+
use Padrino::Reloader::Rack if reload?
|
194
|
+
use Rack::Flash if flash?
|
204
195
|
end
|
205
196
|
|
206
197
|
##
|
@@ -218,12 +209,10 @@ module Padrino
|
|
218
209
|
load_paths.each { |path| Padrino.require_dependencies(File.join(self.root, path)) }
|
219
210
|
end
|
220
211
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
@view_paths = ["views"].collect { |path| File.join(self.root, path) }
|
226
|
-
@view_paths.find { |path| Dir[File.join(path, '/**/*')].any? }
|
212
|
+
private
|
213
|
+
def setup_sessions(builder)
|
214
|
+
return unless sessions
|
215
|
+
builder.use Rack::Session::Cookie, :secret => session_secret, :path => uri_root
|
227
216
|
end
|
228
217
|
end # self
|
229
218
|
|
@@ -88,6 +88,8 @@ module Padrino
|
|
88
88
|
end
|
89
89
|
|
90
90
|
module InstanceMethods
|
91
|
+
attr_reader :current_engine
|
92
|
+
|
91
93
|
def content_type(type=nil, params={}) #:nodoc:
|
92
94
|
type.nil? ? @_content_type : super(type, params)
|
93
95
|
end
|
@@ -114,8 +116,8 @@ module Padrino
|
|
114
116
|
# If an engine is a string then this is a likely a path to be resolved
|
115
117
|
data, engine = *resolve_template(engine, options) if data.nil?
|
116
118
|
|
117
|
-
#
|
118
|
-
|
119
|
+
# Setup root
|
120
|
+
root = settings.respond_to?(:root) ? settings.root : ""
|
119
121
|
|
120
122
|
# Resolve layouts similar to in Rails
|
121
123
|
if (options[:layout].nil? || options[:layout] == true) && !settings.templates.has_key?(:layout)
|
@@ -123,14 +125,21 @@ module Padrino
|
|
123
125
|
options[:layout] = layout_path || false # We need to force layout false so sinatra don't try to render it
|
124
126
|
options[:layout] = false unless layout_engine == engine # TODO allow different layout engine
|
125
127
|
options[:layout_engine] = layout_engine || engine if options[:layout]
|
126
|
-
logger.debug "Resolving layout #{options[:layout]}" if defined?(logger) && options[:layout].present?
|
128
|
+
logger.debug "Resolving layout #{root}/views#{options[:layout]}" if defined?(logger) && options[:layout].present?
|
127
129
|
elsif options[:layout].present?
|
128
130
|
options[:layout] = settings.fetch_layout_path(options[:layout])
|
129
|
-
logger.debug "Resolving layout #{options[:layout]}" if defined?(logger)
|
131
|
+
logger.debug "Resolving layout #{root}/views#{options[:layout]}" if defined?(logger)
|
130
132
|
end
|
131
133
|
|
134
|
+
# Cleanup the template
|
135
|
+
@current_engine, engine_was = engine, @current_engine
|
136
|
+
@_out_buf, _buf_was = "", @_out_buf
|
137
|
+
|
132
138
|
# Pass arguments to Sinatra render method
|
133
139
|
super(engine, data, options.dup, locals, &block)
|
140
|
+
ensure
|
141
|
+
@current_engine = engine_was
|
142
|
+
@_out_buf = _buf_was
|
134
143
|
end
|
135
144
|
|
136
145
|
##
|
@@ -1,6 +1,60 @@
|
|
1
1
|
require 'http_router' unless defined?(HttpRouter)
|
2
2
|
require 'padrino-core/support_lite' unless defined?(SupportLite)
|
3
3
|
|
4
|
+
class Sinatra::Request
|
5
|
+
attr_accessor :route_obj
|
6
|
+
|
7
|
+
def controller
|
8
|
+
route_obj && route_obj.controller
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class HttpRouter #:nodoc:
|
13
|
+
attr_accessor :runner
|
14
|
+
class Route #:nodoc:
|
15
|
+
attr_reader :before_filters, :after_filters
|
16
|
+
attr_accessor :custom_conditions, :use_layout, :controller, :cache
|
17
|
+
|
18
|
+
def add_before_filter(filter)
|
19
|
+
@before_filters ||= []
|
20
|
+
@before_filters << filter
|
21
|
+
arbitrary { |req, params|
|
22
|
+
if req.testing_405?
|
23
|
+
true
|
24
|
+
else
|
25
|
+
old_params = router.runner.params
|
26
|
+
result = catch(:pass) {
|
27
|
+
router.runner.params ||= {}
|
28
|
+
router.runner.params.merge!(params)
|
29
|
+
router.runner.instance_eval(&filter)
|
30
|
+
true
|
31
|
+
} == true
|
32
|
+
router.runner.params = old_params
|
33
|
+
result
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_after_filter(filter)
|
39
|
+
@after_filters ||= []
|
40
|
+
@after_filters << filter
|
41
|
+
end
|
42
|
+
|
43
|
+
def before_filters=(filters)
|
44
|
+
filters.each { |filter| add_before_filter(filter) } if filters
|
45
|
+
end
|
46
|
+
|
47
|
+
def after_filters=(filters)
|
48
|
+
filters.each { |filter| add_after_filter(filter) } if filters
|
49
|
+
end
|
50
|
+
|
51
|
+
def custom_conditions=(custom_conditions)
|
52
|
+
custom_conditions.each { |blk| arbitrary { |req, params| router.runner.instance_eval(&blk) != false } } if custom_conditions
|
53
|
+
@custom_conditions = custom_conditions
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
4
58
|
module Padrino
|
5
59
|
##
|
6
60
|
# Padrino provides advanced routing definition support to make routes and url generation much easier.
|
@@ -12,67 +66,6 @@ module Padrino
|
|
12
66
|
module Routing
|
13
67
|
CONTENT_TYPE_ALIASES = { :htm => :html }
|
14
68
|
|
15
|
-
class ::HttpRouter #:nodoc:
|
16
|
-
attr_accessor :runner
|
17
|
-
class Route #:nodoc:
|
18
|
-
attr_reader :before_filters, :after_filters
|
19
|
-
attr_accessor :custom_conditions, :use_layout, :controller, :cache
|
20
|
-
|
21
|
-
def add_before_filter(filter)
|
22
|
-
@before_filters ||= []
|
23
|
-
@before_filters << filter
|
24
|
-
arbitrary { |req, params, dest|
|
25
|
-
old_params = router.runner.params
|
26
|
-
result = catch(:pass) {
|
27
|
-
router.runner.params ||= {}
|
28
|
-
router.runner.params.merge!(params)
|
29
|
-
router.runner.instance_eval(&filter)
|
30
|
-
true
|
31
|
-
} == true
|
32
|
-
router.runner.params = old_params
|
33
|
-
result
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
def add_after_filter(filter)
|
38
|
-
@after_filters ||= []
|
39
|
-
@after_filters << filter
|
40
|
-
end
|
41
|
-
|
42
|
-
def before_filters=(filters)
|
43
|
-
filters.each { |filter| add_before_filter(filter) } if filters
|
44
|
-
end
|
45
|
-
|
46
|
-
def after_filters=(filters)
|
47
|
-
filters.each { |filter| add_after_filter(filter) } if filters
|
48
|
-
end
|
49
|
-
|
50
|
-
def custom_conditions=(custom_conditions)
|
51
|
-
custom_conditions.each { |blk| arbitrary { |req, params, dest| router.runner.instance_eval(&blk) != false } } if custom_conditions
|
52
|
-
@custom_conditions = custom_conditions
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
module ::Sinatra #:nodoc:
|
58
|
-
class Request #:nodoc:
|
59
|
-
attr_accessor :match
|
60
|
-
|
61
|
-
def controller
|
62
|
-
route && route.controller
|
63
|
-
end
|
64
|
-
|
65
|
-
def route
|
66
|
-
if match.nil?
|
67
|
-
path = Rack::Utils.unescape(path_info)
|
68
|
-
path.empty? ? "/" : path
|
69
|
-
else
|
70
|
-
match.path.route
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end # Request
|
74
|
-
end # Sinatra
|
75
|
-
|
76
69
|
class UnrecognizedException < RuntimeError #:nodoc:
|
77
70
|
end
|
78
71
|
|
@@ -240,6 +233,10 @@ module Padrino
|
|
240
233
|
end
|
241
234
|
alias :urls :router
|
242
235
|
|
236
|
+
def reset_router!
|
237
|
+
@router = HttpRouter.new
|
238
|
+
end
|
239
|
+
|
243
240
|
##
|
244
241
|
# Instance method for url generation like:
|
245
242
|
#
|
@@ -254,9 +251,8 @@ module Padrino
|
|
254
251
|
names, params_array = args.partition{|a| a.is_a?(Symbol)}
|
255
252
|
name = names.join("_").to_sym # route name is concatenated with underscores
|
256
253
|
if params.is_a?(Hash)
|
257
|
-
params.
|
258
|
-
params
|
259
|
-
params.each { |k,v| params[k] = v.to_param if v.respond_to?(:to_param) }
|
254
|
+
params[:format] = params[:format].to_s unless params[:format].nil?
|
255
|
+
params = value_to_param(params)
|
260
256
|
end
|
261
257
|
url = if params_array.empty?
|
262
258
|
router.url(name, params)
|
@@ -287,6 +283,21 @@ module Padrino
|
|
287
283
|
def head(path, *args, &bk); route 'HEAD', path, *args, &bk end
|
288
284
|
|
289
285
|
private
|
286
|
+
# Parse params from the url method
|
287
|
+
def value_to_param(value)
|
288
|
+
case value
|
289
|
+
when Array
|
290
|
+
value.map { |v| value_to_param(v) }.compact
|
291
|
+
when Hash
|
292
|
+
value.inject({}) do |memo, (k,v)|
|
293
|
+
v = value_to_param(v)
|
294
|
+
memo[k] = v unless v.nil?
|
295
|
+
memo
|
296
|
+
end
|
297
|
+
when nil then nil
|
298
|
+
else value.respond_to?(:to_param) ? value.to_param : value
|
299
|
+
end
|
300
|
+
end
|
290
301
|
|
291
302
|
# Add prefix slash if its not present and remove trailing slashes.
|
292
303
|
def conform_uri(uri_string)
|
@@ -317,19 +328,18 @@ module Padrino
|
|
317
328
|
#
|
318
329
|
def route(verb, path, *args, &block)
|
319
330
|
options = case args.size
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
raise
|
331
|
+
when 2
|
332
|
+
args.last.merge(:map => args.first)
|
333
|
+
when 1
|
334
|
+
map = args.shift if args.first.is_a?(String)
|
335
|
+
if args.first.is_a?(Hash)
|
336
|
+
map ? args.first.merge(:map => map) : args.first
|
337
|
+
else
|
338
|
+
{:map => map || args.first}
|
339
|
+
end
|
340
|
+
when 0
|
341
|
+
{}
|
342
|
+
else raise
|
333
343
|
end
|
334
344
|
|
335
345
|
# Do padrino parsing. We dup options so we can build HEAD request correctly
|
@@ -343,7 +353,11 @@ module Padrino
|
|
343
353
|
unbound_method = instance_method("#{verb} #{path}")
|
344
354
|
block =
|
345
355
|
if block.arity != 0
|
346
|
-
|
356
|
+
block_arity = block.arity
|
357
|
+
proc {
|
358
|
+
@block_params = @block_params.slice(0, block_arity) if block_arity > 0
|
359
|
+
unbound_method.bind(self).call(*@block_params)
|
360
|
+
}
|
347
361
|
else
|
348
362
|
proc { unbound_method.bind(self).call }
|
349
363
|
end
|
@@ -356,8 +370,11 @@ module Padrino
|
|
356
370
|
route.cache = options.key?(:cache) ? options.delete(:cache) : @_cache
|
357
371
|
route.send(verb.downcase.to_sym)
|
358
372
|
route.host(options.delete(:host)) if options.key?(:host)
|
359
|
-
route.
|
360
|
-
|
373
|
+
route.user_agent(options.delete(:agent)) if options.key?(:agent)
|
374
|
+
if options.key?(:default_values)
|
375
|
+
defaults = options.delete(:default_values)
|
376
|
+
route.default(defaults) if defaults
|
377
|
+
end
|
361
378
|
options.delete_if do |option, args|
|
362
379
|
if route.send(:significant_variable_names).include?(option)
|
363
380
|
route.matching(option => Array(args).first)
|
@@ -366,7 +383,13 @@ module Padrino
|
|
366
383
|
end
|
367
384
|
|
368
385
|
# Add Sinatra conditions
|
369
|
-
options.each { |option, args|
|
386
|
+
options.each { |option, args|
|
387
|
+
if route.respond_to?(option)
|
388
|
+
route.send(option, *args)
|
389
|
+
else
|
390
|
+
send(option, *args)
|
391
|
+
end
|
392
|
+
}
|
370
393
|
conditions, @conditions = @conditions, []
|
371
394
|
route.custom_conditions = conditions
|
372
395
|
|
@@ -383,6 +406,43 @@ module Padrino
|
|
383
406
|
route.after_filters = @filters[:after] || []
|
384
407
|
end
|
385
408
|
|
409
|
+
route.arbitrary_with_continue do |req, params|
|
410
|
+
if req.testing_405?
|
411
|
+
req.continue[true]
|
412
|
+
else
|
413
|
+
base = self
|
414
|
+
processed = false
|
415
|
+
router.runner.instance_eval do
|
416
|
+
request.route_obj = route
|
417
|
+
@_response_buffer = nil
|
418
|
+
if path.is_a?(Regexp)
|
419
|
+
params_list = req.extra_env['router.regex_match'].to_a
|
420
|
+
params_list.shift
|
421
|
+
@block_params = params_list
|
422
|
+
@params.update({:captures => params_list}.merge(@params || {}))
|
423
|
+
else
|
424
|
+
@block_params = req.params
|
425
|
+
@params.update(params.merge(@params || {}))
|
426
|
+
end
|
427
|
+
pass_block = catch(:pass) do
|
428
|
+
# If present set current controller layout
|
429
|
+
parent_layout = base.instance_variable_get(:@layout)
|
430
|
+
base.instance_variable_set(:@layout, route.use_layout) if route.use_layout
|
431
|
+
# Provide access to the current controller to the request
|
432
|
+
# Now we can eval route, but because we have "throw halt" we need to be
|
433
|
+
# (en)sure to reset old layout and run controller after filters.
|
434
|
+
begin
|
435
|
+
@_response_buffer = catch(:halt) { route_eval(&block) }
|
436
|
+
processed = true
|
437
|
+
ensure
|
438
|
+
base.instance_variable_set(:@layout, parent_layout) if route.use_layout
|
439
|
+
(@_pending_after_filters ||= []).concat(route.after_filters) if route.after_filters
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
req.continue[processed]
|
444
|
+
end
|
445
|
+
end
|
386
446
|
route.to(block)
|
387
447
|
route
|
388
448
|
end
|
@@ -420,10 +480,12 @@ module Padrino
|
|
420
480
|
|
421
481
|
if @_use_format or format_params = options[:provides]
|
422
482
|
process_path_for_provides(path, format_params)
|
483
|
+
options[:matching] ||= {}
|
484
|
+
options[:matching][:format] = /[^\.]+/
|
423
485
|
end
|
424
486
|
|
425
487
|
# Build our controller
|
426
|
-
controller = Array(@_controller).
|
488
|
+
controller = Array(@_controller).map { |c| c.to_s }
|
427
489
|
|
428
490
|
absolute_map = map && map[0] == ?/
|
429
491
|
|
@@ -451,6 +513,7 @@ module Padrino
|
|
451
513
|
path = "#{@_map}/#{path}".squeeze('/') unless absolute_map or @_map.blank?
|
452
514
|
|
453
515
|
# Small reformats
|
516
|
+
path.gsub!(%r{/\?$}, '(/)') # Remove index path
|
454
517
|
path.gsub!(%r{/?index/?}, '/') # Remove index path
|
455
518
|
path.gsub!(%r{//$}, '/') # Remove index path
|
456
519
|
path[0,0] = "/" unless path =~ %r{^\(?/} # Paths must start with a /
|
@@ -469,7 +532,7 @@ module Padrino
|
|
469
532
|
# Used for calculating path in route method
|
470
533
|
#
|
471
534
|
def process_path_for_with_params(path, with_params)
|
472
|
-
File.join(path, Array(with_params).
|
535
|
+
File.join(path, Array(with_params).map(&:inspect).join("/"))
|
473
536
|
end
|
474
537
|
|
475
538
|
##
|
@@ -477,7 +540,7 @@ module Padrino
|
|
477
540
|
# Used for calculating path in route method
|
478
541
|
#
|
479
542
|
def process_path_for_parent_params(path, parent_params)
|
480
|
-
parent_prefix = parent_params.flatten.compact.uniq.
|
543
|
+
parent_prefix = parent_params.flatten.compact.uniq.map do |param|
|
481
544
|
map = (param.respond_to?(:map) && param.map ? param.map : param.to_s)
|
482
545
|
part = "#{map}/:#{param}_id/"
|
483
546
|
part = "(#{part})" if param.respond_to?(:optional) && param.optional?
|
@@ -531,7 +594,8 @@ module Padrino
|
|
531
594
|
|
532
595
|
# per rfc2616-sec14:
|
533
596
|
# Assume */* if no ACCEPT header is given.
|
534
|
-
|
597
|
+
accepts.delete "*/*"
|
598
|
+
if accepts.empty?
|
535
599
|
matching_types = mime_types.slice(0,1)
|
536
600
|
else
|
537
601
|
matching_types = (accepts & mime_types)
|
@@ -552,15 +616,9 @@ module Padrino
|
|
552
616
|
# per rfc2616-sec14:
|
553
617
|
# answer with 406 if accept is given but types to not match any
|
554
618
|
# provided type
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
if settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept
|
560
|
-
if url_format && !matched_format
|
561
|
-
halt 406
|
562
|
-
end
|
563
|
-
end
|
619
|
+
halt 406 if
|
620
|
+
(!url_format && !accepts.empty? && !matched_format) ||
|
621
|
+
(settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept && url_format && !matched_format)
|
564
622
|
|
565
623
|
if matched_format
|
566
624
|
@_content_type = url_format || accept_format || :html
|
@@ -639,39 +697,14 @@ module Padrino
|
|
639
697
|
#
|
640
698
|
def route!(base=self.class, pass_block=nil)
|
641
699
|
base.router.runner = self
|
642
|
-
if base.router and match = base.router.recognize(@request)
|
643
|
-
if match.
|
644
|
-
|
645
|
-
|
646
|
-
if request.match.path.route.regex?
|
647
|
-
params_list = @request.env['rack.request.query_hash']['router.regex_match'].to_a
|
648
|
-
params_list.shift
|
649
|
-
@block_params = params_list
|
650
|
-
@params.update({:captures => params_list}.merge(@params || {}))
|
651
|
-
else
|
652
|
-
@block_params = matched_path.param_values
|
653
|
-
@params.update(matched_path.params.merge(@params || {}))
|
654
|
-
end
|
655
|
-
pass_block = catch(:pass) do
|
656
|
-
# If present set current controller layout
|
657
|
-
parent_layout = base.instance_variable_get(:@layout)
|
658
|
-
base.instance_variable_set(:@layout, matched_path.path.route.use_layout) if matched_path.path.route.use_layout
|
659
|
-
# Provide access to the current controller to the request
|
660
|
-
# Now we can eval route, but because we have "throw halt" we need to be
|
661
|
-
# (en)sure to reset old layout and run controller after filters.
|
662
|
-
begin
|
663
|
-
@_response_buffer = catch(:halt) { route_eval(&matched_path.path.route.dest) }
|
664
|
-
throw :halt, @_response_buffer
|
665
|
-
ensure
|
666
|
-
base.instance_variable_set(:@layout, parent_layout) if matched_path.path.route.use_layout
|
667
|
-
matched_path.path.route.after_filters.each { |aft| throw :pass if instance_eval(&aft) == false } if matched_path.path.route.after_filters
|
668
|
-
end
|
669
|
-
end
|
670
|
-
end
|
671
|
-
elsif match
|
700
|
+
if base.router and match = base.router.recognize(@request.env)
|
701
|
+
if match.respond_to?(:path)
|
702
|
+
throw :halt, @_response_buffer
|
703
|
+
elsif match.respond_to?(:each)
|
672
704
|
route_eval do
|
673
705
|
match[1].each {|k,v| response[k] = v}
|
674
706
|
status match[0]
|
707
|
+
route_missing if match[0] == 404
|
675
708
|
end
|
676
709
|
end
|
677
710
|
end
|
@@ -685,6 +718,8 @@ module Padrino
|
|
685
718
|
route_eval(&pass_block) if pass_block
|
686
719
|
|
687
720
|
route_missing
|
721
|
+
ensure
|
722
|
+
@_pending_after_filters.each { |aft| instance_eval(&aft) } if @_pending_after_filters
|
688
723
|
end
|
689
724
|
end # InstanceMethods
|
690
725
|
end # Routing
|
@@ -10,7 +10,7 @@ def applications
|
|
10
10
|
puts " * %-10s mapped to %s" % [app.name, app.uri_root]
|
11
11
|
end
|
12
12
|
puts
|
13
|
-
Padrino.mounted_apps.
|
13
|
+
Padrino.mounted_apps.map { |app| "#{app.name} => #{app.uri_root}" }
|
14
14
|
end
|
15
15
|
|
16
16
|
# Load apps
|
data/lib/padrino-core/loader.rb
CHANGED
@@ -43,7 +43,7 @@ module Padrino
|
|
43
43
|
set_load_paths(*load_paths) # We set the padrino load paths
|
44
44
|
Padrino.logger # Initialize our logger
|
45
45
|
before_load.each { |bl| bl.call } # Run before hooks
|
46
|
-
dependency_paths.each { |path|
|
46
|
+
dependency_paths.each { |path| require_dependencies(path) }
|
47
47
|
Reloader::Stat.run! # We need to fill our Stat::CACHE
|
48
48
|
after_load.each { |al| al.call } # Run after hooks
|
49
49
|
Thread.current[:padrino_loaded] = true
|
@@ -109,7 +109,6 @@ module Padrino
|
|
109
109
|
files.each do |file|
|
110
110
|
begin
|
111
111
|
Reloader::Stat.safe_load(file)
|
112
|
-
files.delete(file)
|
113
112
|
rescue LoadError => e
|
114
113
|
errors << e
|
115
114
|
failed << file
|
@@ -122,11 +121,10 @@ module Padrino
|
|
122
121
|
end
|
123
122
|
|
124
123
|
# Stop processing if nothing loads or if everything has loaded
|
125
|
-
raise errors.last if
|
126
|
-
break if
|
124
|
+
raise errors.last if failed.size == size_at_start
|
125
|
+
break if failed.empty?
|
127
126
|
end
|
128
127
|
end
|
129
|
-
alias :require_dependency :require_dependencies
|
130
128
|
|
131
129
|
##
|
132
130
|
# Returns default list of path globs to load as dependencies
|
@@ -160,7 +158,6 @@ module Padrino
|
|
160
158
|
FileSet.glob(path) { |file| load(file) }
|
161
159
|
end
|
162
160
|
end
|
163
|
-
alias :load_dependency :load_dependencies
|
164
161
|
|
165
162
|
##
|
166
163
|
# Concat to $LOAD_PATH the given paths
|
data/lib/padrino-core/logger.rb
CHANGED
@@ -30,6 +30,7 @@ module Padrino
|
|
30
30
|
attr_reader :buffer
|
31
31
|
attr_reader :log
|
32
32
|
attr_reader :init_args
|
33
|
+
attr_accessor :log_static
|
33
34
|
|
34
35
|
##
|
35
36
|
# Ruby (standard) logger levels:
|
@@ -63,6 +64,7 @@ module Padrino
|
|
63
64
|
# added. Defaults to true.
|
64
65
|
# :format_datetime:: Format of datetime. Defaults to: "%d/%b/%Y %H:%M:%S"
|
65
66
|
# :format_message:: Format of message. Defaults to: ""%s - - [%s] \"%s\"""
|
67
|
+
# :log_static:: Whether or not to show log messages for static files. Defaults to: false
|
66
68
|
#
|
67
69
|
# ==== Examples
|
68
70
|
#
|
@@ -146,6 +148,7 @@ module Padrino
|
|
146
148
|
# added. Defaults to true.
|
147
149
|
# :format_datetime:: Format of datetime. Defaults to: "%d/%b/%Y %H:%M:%S"
|
148
150
|
# :format_message:: Format of message. Defaults to: ""%s - - [%s] \"%s\"""
|
151
|
+
# :log_static:: Whether or not to show log messages for static files. Defaults to: false
|
149
152
|
#
|
150
153
|
def initialize(options={})
|
151
154
|
@buffer = []
|
@@ -156,6 +159,7 @@ module Padrino
|
|
156
159
|
@mutex = @@mutex[@log] ||= Mutex.new
|
157
160
|
@format_datetime = options[:format_datetime] || "%d/%b/%Y %H:%M:%S"
|
158
161
|
@format_message = options[:format_message] || "%s - [%s] \"%s\""
|
162
|
+
@log_static = options.has_key?(:log_static) ? options[:log_static] : false
|
159
163
|
end
|
160
164
|
|
161
165
|
##
|
@@ -271,10 +275,11 @@ module Padrino
|
|
271
275
|
# "lilith.local - - GET / HTTP/1.1 500 -"
|
272
276
|
# %{%s - %s %s %s%s %s - %d %s %0.4f}
|
273
277
|
#
|
274
|
-
FORMAT = %{%s
|
278
|
+
FORMAT = %{%s (%0.4fms) %s - %s %s%s%s %s - %d %s}
|
275
279
|
|
276
|
-
def initialize(app)
|
280
|
+
def initialize(app, uri_root)
|
277
281
|
@app = app
|
282
|
+
@uri_root = uri_root.sub(/\/$/,"")
|
278
283
|
end
|
279
284
|
|
280
285
|
def call(env)
|
@@ -289,16 +294,19 @@ module Padrino
|
|
289
294
|
now = Time.now
|
290
295
|
length = extract_content_length(header)
|
291
296
|
|
297
|
+
return if env['sinatra.static_file'] and !logger.log_static
|
298
|
+
|
292
299
|
logger.debug FORMAT % [
|
300
|
+
env["REQUEST_METHOD"],
|
301
|
+
now - began_at,
|
293
302
|
env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
|
294
303
|
env["REMOTE_USER"] || "-",
|
295
|
-
|
304
|
+
@uri_root || "",
|
296
305
|
env["PATH_INFO"],
|
297
306
|
env["QUERY_STRING"].empty? ? "" : "?" + env["QUERY_STRING"],
|
298
307
|
env["HTTP_VERSION"],
|
299
308
|
status.to_s[0..3],
|
300
|
-
length
|
301
|
-
now - began_at ]
|
309
|
+
length]
|
302
310
|
end
|
303
311
|
|
304
312
|
def extract_content_length(headers)
|
data/lib/padrino-core/mounter.rb
CHANGED
@@ -15,7 +15,7 @@ module Padrino
|
|
15
15
|
attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host
|
16
16
|
|
17
17
|
def initialize(name, options={})
|
18
|
-
@name = name.to_s
|
18
|
+
@name = name.to_s
|
19
19
|
@app_class = options[:app_class] || @name.camelize
|
20
20
|
@app_file = options[:app_file] || locate_app_file
|
21
21
|
@app_obj = options[:app_obj] || app_constant || locate_app_object
|
@@ -115,45 +115,44 @@ module Padrino
|
|
115
115
|
end
|
116
116
|
|
117
117
|
protected
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
118
|
+
##
|
119
|
+
# Locates and requires the file to load the app constant
|
120
|
+
#
|
121
|
+
def locate_app_object
|
122
|
+
@_app_object ||= begin
|
123
|
+
ensure_app_file!
|
124
|
+
Padrino.require_dependencies(app_file)
|
125
|
+
app_constant
|
126
|
+
end
|
127
127
|
end
|
128
|
-
end
|
129
128
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
129
|
+
##
|
130
|
+
# Returns the determined location of the mounted application main file
|
131
|
+
#
|
132
|
+
def locate_app_file
|
133
|
+
candidates = []
|
134
|
+
candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
|
135
|
+
candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
|
136
|
+
candidates << Padrino.mounted_root(name, "app.rb")
|
137
|
+
candidates << Padrino.root("app", "app.rb")
|
138
|
+
candidates.find { |candidate| File.exist?(candidate) }
|
139
|
+
end
|
141
140
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
141
|
+
###
|
142
|
+
# Raises an exception unless app_file is located properly
|
143
|
+
#
|
144
|
+
def ensure_app_file!
|
145
|
+
message = "Unable to locate source file for app '#{app_class}', try with :app_file => '/path/app.rb'"
|
146
|
+
raise MounterException, message unless @app_file
|
147
|
+
end
|
149
148
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
149
|
+
###
|
150
|
+
# Raises an exception unless app_obj is defined properly
|
151
|
+
#
|
152
|
+
def ensure_app_object!
|
153
|
+
message = "Unable to locate app for '#{app_class}', try with :app_class => 'MyAppClass'"
|
154
|
+
raise MounterException, message unless @app_obj
|
155
|
+
end
|
157
156
|
end
|
158
157
|
|
159
158
|
class << self
|
@@ -34,10 +34,10 @@ module Padrino
|
|
34
34
|
|
35
35
|
##
|
36
36
|
# Specified folders can be excluded from the code reload detection process.
|
37
|
-
# Default excluded directories at Padrino.root are: test, spec, features, tmp, config,
|
37
|
+
# Default excluded directories at Padrino.root are: test, spec, features, tmp, config, db and public
|
38
38
|
#
|
39
39
|
def self.exclude
|
40
|
-
@_exclude ||= %w(test spec tmp features config
|
40
|
+
@_exclude ||= %w(test spec tmp features config public db).map { |path| Padrino.root(path) }
|
41
41
|
end
|
42
42
|
|
43
43
|
##
|
@@ -83,7 +83,7 @@ module Padrino
|
|
83
83
|
# We skip to next file if it is not new and not modified
|
84
84
|
next unless new_file || mtime > previous_mtime
|
85
85
|
# If the file is related to their app (i.e. a controller/mailer/helper)
|
86
|
-
|
86
|
+
Padrino.mounted_apps.find_all { |a| file =~ /^#{File.dirname(a.app_file)}/ }.each do |app|
|
87
87
|
# We need to reload their own app
|
88
88
|
app.app_obj.reload!
|
89
89
|
# App reloading will also perform safe_load of itself so we can go next
|
@@ -254,4 +254,4 @@ module Padrino
|
|
254
254
|
end # self
|
255
255
|
end # Stat
|
256
256
|
end # Reloader
|
257
|
-
end # Padrino
|
257
|
+
end # Padrino
|
@@ -52,7 +52,7 @@ if defined?(ActiveSupport::CoreExtensions::Hash) && !Hash.method_defined?(:slice
|
|
52
52
|
|
53
53
|
def ordered_collect(&block)
|
54
54
|
keys = self.stringify_keys.keys.sort
|
55
|
-
keys.
|
55
|
+
keys.map { |key| block.call(key, self[key.to_sym]) }
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
data/lib/padrino-core/version.rb
CHANGED
data/padrino-core.gemspec
CHANGED
@@ -17,8 +17,9 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.files = %w(.document .gitignore LICENSE README.rdoc Rakefile padrino-core.gemspec) + Dir.glob("{bin,lib,test}/**/*")
|
18
18
|
s.rdoc_options = ["--charset=UTF-8"]
|
19
19
|
s.require_path = "lib"
|
20
|
-
s.add_dependency("
|
21
|
-
s.add_dependency("
|
20
|
+
s.add_dependency("tilt", "~> 1.3.0")
|
21
|
+
s.add_dependency("sinatra", "~> 1.2.3")
|
22
|
+
s.add_dependency("http_router", "~> 0.7.4")
|
22
23
|
s.add_dependency("thor", ">=0.14.3")
|
23
24
|
s.add_dependency("activesupport", ">= 3.0.0")
|
24
25
|
s.add_dependency("tzinfo")
|
data/test/test_logger.rb
CHANGED
@@ -48,8 +48,25 @@ class TestPadrinoLogger < Test::Unit::TestCase
|
|
48
48
|
mock_app { get("/"){ "Foo" } }
|
49
49
|
get "/"
|
50
50
|
assert_equal "Foo", body
|
51
|
-
assert_match /GET
|
51
|
+
assert_match /GET/, Padrino.logger.log.string
|
52
52
|
end
|
53
53
|
|
54
|
+
context "static asset logging" do
|
55
|
+
should 'not log static assets by default' do
|
56
|
+
mock_app { get("/images/something.png"){ env["sinatra.static_file"] = '/public/images/something.png'; "Foo" } }
|
57
|
+
get "/images/something.png"
|
58
|
+
assert_equal "Foo", body
|
59
|
+
assert_match "", Padrino.logger.log.string
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'allow turning on static assets logging' do
|
63
|
+
Padrino.logger.instance_eval{ @log_static = true }
|
64
|
+
mock_app { get("/images/something.png"){ env["sinatra.static_file"] = '/public/images/something.png'; "Foo" } }
|
65
|
+
get "/images/something.png"
|
66
|
+
assert_equal "Foo", body
|
67
|
+
assert_match /GET/, Padrino.logger.log.string
|
68
|
+
Padrino.logger.instance_eval{ @log_static = false }
|
69
|
+
end
|
70
|
+
end
|
54
71
|
end
|
55
72
|
end
|
data/test/test_mounter.rb
CHANGED
@@ -3,9 +3,14 @@ require File.expand_path(File.dirname(__FILE__) + '/helper')
|
|
3
3
|
class TestMounter < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def setup
|
6
|
+
$VERBOSE, @_verbose_was = nil, $VERBOSE
|
6
7
|
Padrino.mounted_apps.clear
|
7
8
|
end
|
8
9
|
|
10
|
+
def teardown
|
11
|
+
$VERBOSE = @_verbose_was
|
12
|
+
end
|
13
|
+
|
9
14
|
context 'for mounter functionality' do
|
10
15
|
|
11
16
|
should 'check methods' do
|
@@ -36,16 +41,16 @@ class TestMounter < Test::Unit::TestCase
|
|
36
41
|
class ::AnApp < Padrino::Application; end
|
37
42
|
Padrino.mount("an_app").to("/")
|
38
43
|
assert_equal AnApp, Padrino.mounted_apps.first.app_obj
|
39
|
-
assert_equal ["an_app"], Padrino.mounted_apps.
|
44
|
+
assert_equal ["an_app"], Padrino.mounted_apps.map(&:name)
|
40
45
|
end
|
41
|
-
|
46
|
+
|
42
47
|
should 'correctly mount an app in a namespace' do
|
43
48
|
module ::SomeNamespace
|
44
49
|
class AnApp < Padrino::Application; end
|
45
50
|
end
|
46
51
|
Padrino.mount("some_namespace/an_app").to("/")
|
47
52
|
assert_equal SomeNamespace::AnApp, Padrino.mounted_apps.first.app_obj
|
48
|
-
assert_equal ["some_namespace/an_app"], Padrino.mounted_apps.
|
53
|
+
assert_equal ["some_namespace/an_app"], Padrino.mounted_apps.map(&:name)
|
49
54
|
end
|
50
55
|
|
51
56
|
should 'mount a primary app to root uri' do
|
@@ -91,7 +96,7 @@ class TestMounter < Test::Unit::TestCase
|
|
91
96
|
assert_equal OneApp, Padrino.mounted_apps[0].app_obj
|
92
97
|
assert_equal TwoApp, Padrino.mounted_apps[1].app_obj
|
93
98
|
assert_equal 2, Padrino.mounted_apps.size, "should not mount duplicate apps"
|
94
|
-
assert_equal ["one_app", "two_app"], Padrino.mounted_apps.
|
99
|
+
assert_equal ["one_app", "two_app"], Padrino.mounted_apps.map(&:name)
|
95
100
|
end
|
96
101
|
|
97
102
|
should 'change mounted_root' do
|
@@ -9,8 +9,8 @@ class TestComplexReloader < Test::Unit::TestCase
|
|
9
9
|
Padrino.mounted_apps.clear
|
10
10
|
Padrino.mount("complex_1_demo").to("/complex_1_demo")
|
11
11
|
Padrino.mount("complex_2_demo").to("/complex_2_demo")
|
12
|
-
assert_equal ["/complex_1_demo", "/complex_2_demo"], Padrino.mounted_apps.
|
13
|
-
assert_equal ["complex_1_demo", "complex_2_demo"], Padrino.mounted_apps.
|
12
|
+
assert_equal ["/complex_1_demo", "/complex_2_demo"], Padrino.mounted_apps.map(&:uri_root)
|
13
|
+
assert_equal ["complex_1_demo", "complex_2_demo"], Padrino.mounted_apps.map(&:name)
|
14
14
|
assert Complex1Demo.reload?
|
15
15
|
assert Complex2Demo.reload?
|
16
16
|
assert_match %r{fixtures/apps/complex.rb}, Complex1Demo.app_file
|
@@ -39,26 +39,28 @@ class TestComplexReloader < Test::Unit::TestCase
|
|
39
39
|
new_phrase = "The magick number is: #{rand(100)}!"
|
40
40
|
buffer = File.read(Complex1Demo.app_file)
|
41
41
|
new_buffer = buffer.gsub(/The magick number is: \d+!/, new_phrase)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
begin
|
43
|
+
File.open(Complex1Demo.app_file, "w") { |f| f.write(new_buffer) }
|
44
|
+
sleep 1.2 # We need at least a cooldown of 1 sec.
|
45
|
+
get "/complex_2_demo"
|
46
|
+
assert_equal new_phrase, body
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
get "/complex_2_demo"
|
52
|
-
assert_equal 200, status
|
48
|
+
# Re-Check that we didn't forget any route
|
49
|
+
get "/complex_1_demo"
|
50
|
+
assert_equal "Given random #{LibDemo.give_me_a_random}", body
|
53
51
|
|
54
|
-
|
55
|
-
|
52
|
+
get "/complex_2_demo"
|
53
|
+
assert_equal 200, status
|
56
54
|
|
57
|
-
|
58
|
-
|
55
|
+
get "/complex_1_demo/old"
|
56
|
+
assert_equal 200, status
|
59
57
|
|
60
|
-
|
61
|
-
|
58
|
+
get "/complex_2_demo/old"
|
59
|
+
assert_equal 200, status
|
60
|
+
ensure
|
61
|
+
# Now we need to prevent to commit a new changed file so we revert it
|
62
|
+
File.open(Complex1Demo.app_file, "w") { |f| f.write(buffer) }
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
@@ -47,7 +47,7 @@ class TestSimpleReloader < Test::Unit::TestCase
|
|
47
47
|
should 'correctly instantiate SimpleDemo fixture' do
|
48
48
|
Padrino.mounted_apps.clear
|
49
49
|
Padrino.mount("simple_demo").to("/")
|
50
|
-
assert_equal ["simple_demo"], Padrino.mounted_apps.
|
50
|
+
assert_equal ["simple_demo"], Padrino.mounted_apps.map(&:name)
|
51
51
|
assert SimpleDemo.reload?
|
52
52
|
assert_match %r{fixtures/apps/simple.rb}, SimpleDemo.app_file
|
53
53
|
end
|
@@ -71,6 +71,7 @@ class TestSimpleReloader < Test::Unit::TestCase
|
|
71
71
|
|
72
72
|
should 'correctly reset SimpleDemo fixture' do
|
73
73
|
@app = SimpleDemo
|
74
|
+
@app.reload!
|
74
75
|
get "/rand"
|
75
76
|
assert ok?
|
76
77
|
last_body = body
|
data/test/test_router.rb
CHANGED
@@ -106,8 +106,8 @@ class TestRouter < Test::Unit::TestCase
|
|
106
106
|
should "works with padrino core applications" do
|
107
107
|
Padrino.mounted_apps.clear
|
108
108
|
Padrino.mount("simple_demo").host("padrino.org")
|
109
|
-
assert_equal ["simple_demo"], Padrino.mounted_apps.
|
110
|
-
assert_equal ["padrino.org"], Padrino.mounted_apps.
|
109
|
+
assert_equal ["simple_demo"], Padrino.mounted_apps.map(&:name)
|
110
|
+
assert_equal ["padrino.org"], Padrino.mounted_apps.map(&:app_host)
|
111
111
|
|
112
112
|
res = Rack::MockRequest.new(Padrino.application).get("/")
|
113
113
|
assert res.not_found?
|
data/test/test_routing.rb
CHANGED
@@ -4,11 +4,6 @@ class FooError < RuntimeError; end
|
|
4
4
|
|
5
5
|
|
6
6
|
class TestRouting < Test::Unit::TestCase
|
7
|
-
should 'use padrinos url method' do
|
8
|
-
mock_app { }
|
9
|
-
assert_equal @app.method(:url).owner, Padrino::Routing::ClassMethods
|
10
|
-
end
|
11
|
-
|
12
7
|
should 'ignore trailing delimiters for basic route' do
|
13
8
|
mock_app do
|
14
9
|
get("/foo"){ "okey" }
|
@@ -35,23 +30,6 @@ class TestRouting < Test::Unit::TestCase
|
|
35
30
|
}
|
36
31
|
end
|
37
32
|
|
38
|
-
should_eventually 'generate a url using route string with params' do
|
39
|
-
mock_app do
|
40
|
-
get("/show/:id/:name"){ "okey" }
|
41
|
-
end
|
42
|
-
|
43
|
-
assert_equal "/show/1/foo", @app.url_for("/show/:id/:name", :id => 1, :name => "foo")
|
44
|
-
end
|
45
|
-
|
46
|
-
should 'work correctly with sinatra redirects' do
|
47
|
-
mock_app do
|
48
|
-
get(:index){ redirect url(:index) }
|
49
|
-
end
|
50
|
-
|
51
|
-
get "/"
|
52
|
-
assert_equal "http://example.org/", headers['Location']
|
53
|
-
end
|
54
|
-
|
55
33
|
should 'accept regexp routes' do
|
56
34
|
mock_app do
|
57
35
|
get(%r{/fob|/baz}) { "regexp" }
|
@@ -128,7 +106,7 @@ class TestRouting < Test::Unit::TestCase
|
|
128
106
|
assert_equal ["POST"], app.routes[2].as_options[:conditions][:request_method]
|
129
107
|
end
|
130
108
|
|
131
|
-
should 'generate basic urls'do
|
109
|
+
should 'generate basic urls' do
|
132
110
|
mock_app do
|
133
111
|
get(:foo){ "/foo" }
|
134
112
|
get(:foo, :with => :id){ |id| "/foo/#{id}" }
|
@@ -252,6 +230,31 @@ class TestRouting < Test::Unit::TestCase
|
|
252
230
|
assert_equal 'json', body
|
253
231
|
end
|
254
232
|
|
233
|
+
should "send the appropriate number of params" do
|
234
|
+
mock_app do
|
235
|
+
get('/id/:user_id', :provides => [:json]) { |user_id| user_id}
|
236
|
+
end
|
237
|
+
get '/id/5.json'
|
238
|
+
assert_equal '5', body
|
239
|
+
end
|
240
|
+
|
241
|
+
should "allow .'s in param values" do
|
242
|
+
mock_app do
|
243
|
+
get('/id/:email', :provides => [:json]) { |email, format| [email, format] * '/' }
|
244
|
+
end
|
245
|
+
get '/id/foo@bar.com.json'
|
246
|
+
assert_equal 'foo@bar.com/json', body
|
247
|
+
end
|
248
|
+
|
249
|
+
should "set correct content_type for Accept not equal to */* even if */* also provided" do
|
250
|
+
mock_app do
|
251
|
+
get("/foo", :provides => [:html, :js, :xml]) { content_type.to_s }
|
252
|
+
end
|
253
|
+
|
254
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript, */*;q=0.5' }
|
255
|
+
assert_equal 'js', body
|
256
|
+
end
|
257
|
+
|
255
258
|
should "return the first content type in provides if accept header is empty" do
|
256
259
|
mock_app do
|
257
260
|
get(:a, :provides => [:js]){ content_type.to_s }
|
@@ -326,7 +329,7 @@ class TestRouting < Test::Unit::TestCase
|
|
326
329
|
should "should inject the route into the request" do
|
327
330
|
mock_app do
|
328
331
|
controller :posts do
|
329
|
-
get(:index) { request.
|
332
|
+
get(:index) { request.route_obj.named.to_s }
|
330
333
|
end
|
331
334
|
end
|
332
335
|
get "/posts"
|
@@ -863,6 +866,14 @@ class TestRouting < Test::Unit::TestCase
|
|
863
866
|
assert_equal 'html', body
|
864
867
|
end
|
865
868
|
|
869
|
+
should "set content_type to :js if Accept includes both application/javascript and */*;q=0.5" do
|
870
|
+
mock_app do
|
871
|
+
get("/foo", :provides => [:html, :js]) { content_type.to_s }
|
872
|
+
end
|
873
|
+
get '/foo', {}, { 'HTTP_ACCEPT' => 'application/javascript, */*;q=0.5' }
|
874
|
+
assert_equal 'js', body
|
875
|
+
end
|
876
|
+
|
866
877
|
should 'allows custom route-conditions to be set via route options and halt' do
|
867
878
|
protector = Module.new do
|
868
879
|
def protect(*args)
|
@@ -1132,7 +1143,6 @@ class TestRouting < Test::Unit::TestCase
|
|
1132
1143
|
assert_equal "This is the get index.json", body
|
1133
1144
|
get "/.js"
|
1134
1145
|
assert_equal 404, status
|
1135
|
-
assert_match "Sinatra doesn't know this ditty", body
|
1136
1146
|
post "/.json"
|
1137
1147
|
assert_equal "This is the post index.json", body
|
1138
1148
|
post "/.js"
|
@@ -1330,4 +1340,39 @@ class TestRouting < Test::Unit::TestCase
|
|
1330
1340
|
assert_equal 200, status
|
1331
1341
|
assert_equal 'okay', body
|
1332
1342
|
end
|
1343
|
+
|
1344
|
+
should 'parse nested params' do
|
1345
|
+
mock_app do
|
1346
|
+
get(:index) { params.inspect }
|
1347
|
+
end
|
1348
|
+
get "/?account[name]=foo&account[surname]=bar"
|
1349
|
+
assert_equal '{"account"=>{"name"=>"foo", "surname"=>"bar"}}', body
|
1350
|
+
get @app.url(:index, "account[name]" => "foo", "account[surname]" => "bar")
|
1351
|
+
assert_equal '{"account"=>{"name"=>"foo", "surname"=>"bar"}}', body
|
1352
|
+
end
|
1353
|
+
|
1354
|
+
should 'render sinatra NotFound page' do
|
1355
|
+
mock_app { set :environment, :development }
|
1356
|
+
get "/"
|
1357
|
+
assert_equal 404, status
|
1358
|
+
assert_match /Sinatra doesn\'t know this ditty./, body
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
should 'render a custom NotFound page' do
|
1362
|
+
mock_app do
|
1363
|
+
error(Sinatra::NotFound) { "not found" }
|
1364
|
+
end
|
1365
|
+
get "/"
|
1366
|
+
assert_equal 404, status
|
1367
|
+
assert_match /not found/, body
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
should 'render a custom 404 page' do
|
1371
|
+
mock_app do
|
1372
|
+
error(404) { "not found" }
|
1373
|
+
end
|
1374
|
+
get "/"
|
1375
|
+
assert_equal 404, status
|
1376
|
+
assert_match /not found/, body
|
1377
|
+
end
|
1333
1378
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: padrino-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 25
|
10
|
+
version: 0.9.25
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Padrino Team
|
@@ -18,45 +18,61 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2011-04-
|
21
|
+
date: 2011-04-27 00:00:00 +02:00
|
22
22
|
default_executable: padrino
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
|
-
name:
|
25
|
+
name: tilt
|
26
26
|
prerelease: false
|
27
27
|
requirement: &id001 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
hash:
|
32
|
+
hash: 27
|
33
33
|
segments:
|
34
34
|
- 1
|
35
|
-
-
|
35
|
+
- 3
|
36
36
|
- 0
|
37
|
-
version: 1.
|
37
|
+
version: 1.3.0
|
38
38
|
type: :runtime
|
39
39
|
version_requirements: *id001
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
|
-
name:
|
41
|
+
name: sinatra
|
42
42
|
prerelease: false
|
43
43
|
requirement: &id002 !ruby/object:Gem::Requirement
|
44
44
|
none: false
|
45
45
|
requirements:
|
46
46
|
- - ~>
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
hash:
|
48
|
+
hash: 25
|
49
|
+
segments:
|
50
|
+
- 1
|
51
|
+
- 2
|
52
|
+
- 3
|
53
|
+
version: 1.2.3
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id002
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: http_router
|
58
|
+
prerelease: false
|
59
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ~>
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 11
|
49
65
|
segments:
|
50
66
|
- 0
|
51
|
-
-
|
67
|
+
- 7
|
52
68
|
- 4
|
53
|
-
version: 0.
|
69
|
+
version: 0.7.4
|
54
70
|
type: :runtime
|
55
|
-
version_requirements: *
|
71
|
+
version_requirements: *id003
|
56
72
|
- !ruby/object:Gem::Dependency
|
57
73
|
name: thor
|
58
74
|
prerelease: false
|
59
|
-
requirement: &
|
75
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
60
76
|
none: false
|
61
77
|
requirements:
|
62
78
|
- - ">="
|
@@ -68,11 +84,11 @@ dependencies:
|
|
68
84
|
- 3
|
69
85
|
version: 0.14.3
|
70
86
|
type: :runtime
|
71
|
-
version_requirements: *
|
87
|
+
version_requirements: *id004
|
72
88
|
- !ruby/object:Gem::Dependency
|
73
89
|
name: activesupport
|
74
90
|
prerelease: false
|
75
|
-
requirement: &
|
91
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
76
92
|
none: false
|
77
93
|
requirements:
|
78
94
|
- - ">="
|
@@ -84,11 +100,11 @@ dependencies:
|
|
84
100
|
- 0
|
85
101
|
version: 3.0.0
|
86
102
|
type: :runtime
|
87
|
-
version_requirements: *
|
103
|
+
version_requirements: *id005
|
88
104
|
- !ruby/object:Gem::Dependency
|
89
105
|
name: tzinfo
|
90
106
|
prerelease: false
|
91
|
-
requirement: &
|
107
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
92
108
|
none: false
|
93
109
|
requirements:
|
94
110
|
- - ">="
|
@@ -98,7 +114,7 @@ dependencies:
|
|
98
114
|
- 0
|
99
115
|
version: "0"
|
100
116
|
type: :runtime
|
101
|
-
version_requirements: *
|
117
|
+
version_requirements: *id006
|
102
118
|
description: The Padrino core gem required for use of this framework
|
103
119
|
email: padrinorb@gmail.com
|
104
120
|
executables:
|