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.
@@ -63,7 +63,7 @@ module Padrino
63
63
  # MyApp.reset_routes!
64
64
  #
65
65
  def reset_routes!
66
- router.reset!
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', self.uri_root) }
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 if Padrino.logger && (Padrino.logger.level == 0 && padrino_logging?)
202
- use Padrino::Reloader::Rack if reload?
203
- use Rack::Flash if flash? && sessions?
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
- # Returns the path to the views directory from root by returning the first that is found
223
- #
224
- def find_view_path
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
- # Sinatra 1.0 requires an outvar for erb and erubis templates
118
- options[:outvar] ||= '@_out_buf' if [:erb, :erubis] & [engine]
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.delete_if { |k,v| v.nil? }
258
- params[:format] = params[:format].to_s if params.has_key?(:format)
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
- when 2
321
- args.last.merge(:map => args.first)
322
- when 1
323
- map = args.shift if args.first.is_a?(String)
324
- if args.first.is_a?(Hash)
325
- map ? args.first.merge(:map => map) : args.first
326
- else
327
- {:map => map || args.first}
328
- end
329
- when 0
330
- {}
331
- else
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
- proc { unbound_method.bind(self).call(*@block_params) }
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.condition(:user_agent => options.delete(:agent)) if options.key?(:agent)
360
- route.default_values = options.delete(:default_values)
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| send(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).collect { |c| c.to_s }
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).collect(&:inspect).join("/"))
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.collect do |param|
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
- if accepts.empty? || accepts.any? { |a| a == "*/*" }
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
- if !url_format && !accepts.empty? && !matched_format
556
- halt 406
557
- end
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.first.respond_to?(:path)
644
- match.each do |matched_path|
645
- request.match = matched_path
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
@@ -25,6 +25,7 @@ module Padrino
25
25
 
26
26
  desc "stop", "Stops the Padrino application"
27
27
  def stop
28
+ prepare :stop
28
29
  require File.expand_path(File.dirname(__FILE__) + "/adapter")
29
30
  Padrino::Cli::Adapter.stop
30
31
  end
@@ -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.collect { |app| "#{app.name} => #{app.uri_root}" }
13
+ Padrino.mounted_apps.map { |app| "#{app.name} => #{app.uri_root}" }
14
14
  end
15
15
 
16
16
  # Load apps
@@ -28,6 +28,11 @@ task :environment do
28
28
  end
29
29
  end
30
30
 
31
+ desc "Generate a secret key"
32
+ task :secret do
33
+ shell.say '%x' % rand(2**255)
34
+ end
35
+
31
36
  # lists all routes of a given app
32
37
  def list_app_routes(app, args)
33
38
  app_routes = app.named_routes
@@ -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| require_dependency(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 files.size == size_at_start && files.present?
126
- break if files.empty?
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
@@ -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 - %s %s %s%s %s - %d %s %0.4f}
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
- env["REQUEST_METHOD"],
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)
@@ -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.underscore
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
- # Locates and requires the file to load the app constant
121
- #
122
- def locate_app_object
123
- @_app_object ||= begin
124
- ensure_app_file!
125
- Padrino.require_dependencies(app_file)
126
- app_constant
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
- # Returns the determined location of the mounted application main file
132
- #
133
- def locate_app_file
134
- candidates = []
135
- candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
136
- candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
137
- candidates << Padrino.mounted_root(name, "app.rb")
138
- candidates << Padrino.root("app", "app.rb")
139
- candidates.find { |candidate| File.exist?(candidate) }
140
- end
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
- # Raises an exception unless app_file is located properly
144
- #
145
- def ensure_app_file!
146
- message = "Unable to locate source file for app '#{name}', try with :app_file => '/path/app.rb'"
147
- raise MounterException, message unless @app_file
148
- end
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
- # Raises an exception unless app_obj is defined properly
152
- #
153
- def ensure_app_object!
154
- message = "Unable to locate app for '#{name}', try with :app_class => 'MyAppClass'"
155
- raise MounterException, message unless @app_obj
156
- end
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, lib, db and public
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 lib public db).map { |path| Padrino.root(path) }
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
- if app = Padrino.mounted_apps.find { |a| file =~ /^#{File.dirname(a.app_file)}/ }
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.collect { |key| block.call(key, self[key.to_sym]) }
55
+ keys.map { |key| block.call(key, self[key.to_sym]) }
56
56
  end
57
57
  end
58
58
  end
@@ -5,7 +5,7 @@
5
5
  # without include full padrino core.
6
6
  #
7
7
  module Padrino
8
- VERSION = '0.9.24' unless defined?(Padrino::VERSION)
8
+ VERSION = '0.9.25' unless defined?(Padrino::VERSION)
9
9
  ##
10
10
  # Return the current Padrino version
11
11
  #
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("sinatra", "~> 1.2.0")
21
- s.add_dependency("http_router", "~> 0.5.4")
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")
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  SimpleDemo.controllers do
16
16
  get "/" do
17
- 'The magick number is: 39!' # Change only the number!!!
17
+ 'The magick number is: 4!' # Change only the number!!!
18
18
  end
19
19
 
20
20
  get "/rand" do
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 \/ - 200/, Padrino.logger.log.string
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.collect(&:name)
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.collect(&:name)
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.collect(&:name)
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.collect(&:uri_root)
13
- assert_equal ["complex_1_demo", "complex_2_demo"], Padrino.mounted_apps.collect(&:name)
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
- File.open(Complex1Demo.app_file, "w") { |f| f.write(new_buffer) }
43
- sleep 1.2 # We need at least a cooldown of 1 sec.
44
- get "/complex_2_demo"
45
- assert_equal new_phrase, body
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
- # Re-Check that we didn't forget any route
48
- get "/complex_1_demo"
49
- assert_equal "Given random #{LibDemo.give_me_a_random}", body
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
- get "/complex_1_demo/old"
55
- assert_equal 200, status
52
+ get "/complex_2_demo"
53
+ assert_equal 200, status
56
54
 
57
- get "/complex_2_demo/old"
58
- assert_equal 200, status
55
+ get "/complex_1_demo/old"
56
+ assert_equal 200, status
59
57
 
60
- # Now we need to prevent to commit a new changed file so we revert it
61
- File.open(Complex1Demo.app_file, "w") { |f| f.write(buffer) }
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.collect(&:name)
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.collect(&:name)
110
- assert_equal ["padrino.org"], Padrino.mounted_apps.collect(&:app_host)
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.route.named.to_s }
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: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 24
10
- version: 0.9.24
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-28 00:00:00 +02:00
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: sinatra
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: 31
32
+ hash: 27
33
33
  segments:
34
34
  - 1
35
- - 2
35
+ - 3
36
36
  - 0
37
- version: 1.2.0
37
+ version: 1.3.0
38
38
  type: :runtime
39
39
  version_requirements: *id001
40
40
  - !ruby/object:Gem::Dependency
41
- name: http_router
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: 3
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
- - 5
67
+ - 7
52
68
  - 4
53
- version: 0.5.4
69
+ version: 0.7.4
54
70
  type: :runtime
55
- version_requirements: *id002
71
+ version_requirements: *id003
56
72
  - !ruby/object:Gem::Dependency
57
73
  name: thor
58
74
  prerelease: false
59
- requirement: &id003 !ruby/object:Gem::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: *id003
87
+ version_requirements: *id004
72
88
  - !ruby/object:Gem::Dependency
73
89
  name: activesupport
74
90
  prerelease: false
75
- requirement: &id004 !ruby/object:Gem::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: *id004
103
+ version_requirements: *id005
88
104
  - !ruby/object:Gem::Dependency
89
105
  name: tzinfo
90
106
  prerelease: false
91
- requirement: &id005 !ruby/object:Gem::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: *id005
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: