merb-core 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Rakefile +61 -11
  2. data/bin/merb +5 -1
  3. data/lib/merb-core.rb +202 -25
  4. data/lib/merb-core/autoload.rb +19 -17
  5. data/lib/merb-core/bootloader.rb +84 -71
  6. data/lib/merb-core/config.rb +19 -14
  7. data/lib/merb-core/controller/abstract_controller.rb +16 -17
  8. data/lib/merb-core/controller/exceptions.rb +115 -70
  9. data/lib/merb-core/controller/merb_controller.rb +62 -38
  10. data/lib/merb-core/controller/mime.rb +1 -1
  11. data/lib/merb-core/controller/mixins/authentication.rb +87 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +16 -15
  13. data/lib/merb-core/controller/mixins/render.rb +113 -19
  14. data/lib/merb-core/controller/mixins/responder.rb +8 -2
  15. data/lib/merb-core/controller/template.rb +1 -1
  16. data/lib/merb-core/core_ext.rb +1 -0
  17. data/lib/merb-core/core_ext/class.rb +113 -6
  18. data/lib/merb-core/core_ext/hash.rb +43 -39
  19. data/lib/merb-core/core_ext/kernel.rb +75 -38
  20. data/lib/merb-core/core_ext/mash.rb +4 -4
  21. data/lib/merb-core/core_ext/object.rb +18 -7
  22. data/lib/merb-core/core_ext/set.rb +9 -4
  23. data/lib/merb-core/core_ext/string.rb +29 -9
  24. data/lib/merb-core/core_ext/time.rb +13 -0
  25. data/lib/merb-core/dispatch/cookies.rb +1 -2
  26. data/lib/merb-core/dispatch/dispatcher.rb +18 -10
  27. data/lib/merb-core/dispatch/exceptions.html.erb +1 -1
  28. data/lib/merb-core/dispatch/request.rb +3 -0
  29. data/lib/merb-core/dispatch/router.rb +10 -7
  30. data/lib/merb-core/dispatch/router/behavior.rb +36 -27
  31. data/lib/merb-core/dispatch/router/route.rb +7 -2
  32. data/lib/merb-core/dispatch/session/cookie.rb +4 -4
  33. data/lib/merb-core/dispatch/session/memcached.rb +17 -5
  34. data/lib/merb-core/logger.rb +2 -2
  35. data/lib/merb-core/plugins.rb +16 -4
  36. data/lib/merb-core/rack/adapter/ebb.rb +4 -1
  37. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -0
  38. data/lib/merb-core/rack/adapter/fcgi.rb +1 -0
  39. data/lib/merb-core/rack/adapter/mongrel.rb +1 -0
  40. data/lib/merb-core/rack/adapter/runner.rb +1 -0
  41. data/lib/merb-core/rack/adapter/thin.rb +3 -1
  42. data/lib/merb-core/rack/adapter/webrick.rb +1 -0
  43. data/lib/merb-core/rack/application.rb +17 -1
  44. data/lib/merb-core/server.rb +78 -28
  45. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -3
  46. data/lib/merb-core/test/helpers/request_helper.rb +81 -27
  47. data/lib/merb-core/test/helpers/view_helper.rb +1 -1
  48. data/lib/merb-core/test/matchers/controller_matchers.rb +55 -5
  49. data/lib/merb-core/test/matchers/route_matchers.rb +8 -17
  50. data/lib/merb-core/test/matchers/view_matchers.rb +53 -11
  51. data/lib/merb-core/test/run_specs.rb +22 -14
  52. data/lib/merb-core/test/tasks/spectasks.rb +54 -33
  53. data/lib/merb-core/vendor/facets/inflect.rb +91 -2
  54. data/lib/merb-core/version.rb +2 -2
  55. data/spec/private/config/config_spec.rb +54 -26
  56. data/spec/private/core_ext/class_spec.rb +22 -0
  57. data/spec/private/core_ext/hash_spec.rb +70 -54
  58. data/spec/private/core_ext/kernel_spec.rb +149 -14
  59. data/spec/private/core_ext/object_spec.rb +92 -10
  60. data/spec/private/core_ext/string_spec.rb +162 -4
  61. data/spec/private/core_ext/time_spec.rb +16 -0
  62. data/spec/private/dispatch/bootloader_spec.rb +24 -0
  63. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +1 -1
  64. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +1 -1
  65. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +1 -1
  66. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +1 -1
  67. data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
  68. data/spec/private/dispatch/fixture/log/merb_test.log +138 -0
  69. data/spec/private/plugins/plugin_spec.rb +79 -8
  70. data/spec/private/rack/application_spec.rb +1 -1
  71. data/spec/public/abstract_controller/controllers/filters.rb +26 -0
  72. data/spec/public/abstract_controller/controllers/helpers.rb +2 -2
  73. data/spec/public/abstract_controller/controllers/partial.rb +2 -2
  74. data/spec/public/abstract_controller/controllers/render.rb +16 -4
  75. data/spec/public/abstract_controller/filter_spec.rb +8 -0
  76. data/spec/public/abstract_controller/render_spec.rb +12 -0
  77. data/spec/public/controller/authentication_spec.rb +103 -0
  78. data/spec/public/controller/base_spec.rb +4 -3
  79. data/spec/public/controller/controllers/authentication.rb +47 -0
  80. data/spec/public/controller/controllers/base.rb +1 -0
  81. data/spec/public/controller/controllers/display.rb +30 -0
  82. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
  83. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
  84. data/spec/public/controller/display_spec.rb +17 -0
  85. data/spec/public/controller/spec_helper.rb +1 -0
  86. data/spec/public/controller/url_spec.rb +25 -7
  87. data/spec/public/core/merb_core_spec.rb +34 -0
  88. data/spec/public/directory_structure/directory/app/controllers/custom.rb +2 -2
  89. data/spec/public/directory_structure/directory/log/merb_test.log +48 -0
  90. data/spec/public/logger/logger_spec.rb +10 -4
  91. data/spec/public/reloading/directory/app/controllers/reload.rb +1 -1
  92. data/spec/public/reloading/directory/log/merb_test.log +13 -0
  93. data/spec/public/reloading/reload_spec.rb +23 -22
  94. data/spec/public/request/request_spec.rb +2 -0
  95. data/spec/public/router/nested_resources_spec.rb +7 -0
  96. data/spec/public/router/resources_spec.rb +46 -1
  97. data/spec/public/router/special_spec.rb +5 -1
  98. data/spec/public/test/controller_matchers_spec.rb +25 -1
  99. data/spec/public/test/controllers/spec_helper_controller.rb +8 -0
  100. data/spec/public/test/request_helper_spec.rb +52 -1
  101. data/spec/public/test/route_matchers_spec.rb +27 -25
  102. data/spec/public/test/view_helper_spec.rb +1 -1
  103. data/spec/public/test/view_matchers_spec.rb +148 -72
  104. metadata +23 -3
@@ -169,7 +169,7 @@
169
169
  <div class="internalError">
170
170
 
171
171
  <div class="header">
172
- <h1><%= @exception_name %> <sup class="error_<%= @exception.class::STATUS %>"><%= @exception.class::STATUS %></sup></h1>
172
+ <h1><%= @exception_name %> <sup class="error_<%= @exception.class.status %>"><%= @exception.class.status %></sup></h1>
173
173
  <% if show_details = ::Merb::Config[:exception_details] -%>
174
174
  <h2><%= html_escape(@exception.message) %></h2>
175
175
  <% else -%>
@@ -549,6 +549,9 @@ module Merb
549
549
  parms[key] = val
550
550
  elsif after == "[]"
551
551
  (parms[key] ||= []) << val
552
+ elsif after =~ %r(^\[\])
553
+ parms[key] ||= []
554
+ parms[key] << normalize_params({}, after, val)
552
555
  else
553
556
  parms[key] ||= {}
554
557
  parms[key] = normalize_params(parms[key], after, val)
@@ -11,6 +11,7 @@ module Merb
11
11
 
12
12
  @@named_routes = {}
13
13
  @@routes = []
14
+ @@compiler_mutex = Mutex.new
14
15
  cattr_accessor :routes, :named_routes
15
16
 
16
17
  class << self
@@ -52,13 +53,15 @@ module Merb
52
53
  # ==== Returns
53
54
  # String:: A routing lambda statement generated from the routes.
54
55
  def compiled_statement
55
- @@compiled_statement = "def match(request)\n"
56
- @@compiled_statement << " params = request.params\n"
57
- @@compiled_statement << " cached_path = request.path\n cached_method = request.method.to_s\n "
58
- @@routes.each_with_index { |route, i| @@compiled_statement << route.compile(i == 0) }
59
- @@compiled_statement << " else\n [nil, {}]\n"
60
- @@compiled_statement << " end\n"
61
- @@compiled_statement << "end"
56
+ @@compiler_mutex.synchronize do
57
+ @@compiled_statement = "def match(request)\n"
58
+ @@compiled_statement << " params = request.params\n"
59
+ @@compiled_statement << " cached_path = request.path\n cached_method = request.method.to_s\n "
60
+ @@routes.each_with_index { |route, i| @@compiled_statement << route.compile(i == 0) }
61
+ @@compiled_statement << " else\n [nil, {}]\n"
62
+ @@compiled_statement << " end\n"
63
+ @@compiled_statement << "end"
64
+ end
62
65
  end
63
66
 
64
67
  # Defines the match function for this class based on the
@@ -318,6 +318,8 @@ module Merb
318
318
  # :member<Hash>:
319
319
  # Special settings and resources related to a specific member of this
320
320
  # resource.
321
+ # :keys<Array>:
322
+ # A list of the keys to be used instead of :id with the resource in the order of the url.
321
323
  #
322
324
  # ==== Block parameters
323
325
  # next_level<Behavior>:: The child behavior.
@@ -336,6 +338,7 @@ module Merb
336
338
  # # GET /posts/:id(\.:format)? :action => "show"
337
339
  # # GET /posts/:id[;/]edit :action => "edit"
338
340
  # # PUT /posts/:id(\.:format)? :action => "update"
341
+ # # GET /posts/:id[;/]delete :action => "delete"
339
342
  # # DELETE /posts/:id(\.:format)? :action => "destroy"
340
343
  #
341
344
  # # Nesting resources
@@ -350,15 +353,16 @@ module Merb
350
353
  next_level = match "/#{name}"
351
354
 
352
355
  name_prefix = options.delete :name_prefix
356
+ matched_keys = options[:keys] ? options.delete(:keys).map{|k| ":#{k}"}.join("/") : ":id"
353
357
 
354
358
  if name_prefix.nil? && !namespace.nil?
355
359
  name_prefix = namespace_to_name_prefix namespace
356
360
  end
357
-
361
+
358
362
  unless @@parent_resource.empty?
359
363
  parent_resource = namespace_to_name_prefix @@parent_resource.join('_')
360
364
  end
361
-
365
+
362
366
  options[:controller] ||= merged_params[:controller] || name.to_s
363
367
 
364
368
  singular = name.to_s.singularize
@@ -371,41 +375,45 @@ module Merb
371
375
  if member = options.delete(:member)
372
376
  member.each_pair do |action, methods|
373
377
  behaviors << Behavior.new(
374
- { :path => %r{^/:id[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
375
- { :action => action.to_s }, next_level
378
+ { :path => %r{^/#{matched_keys}[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
379
+ { :action => action.to_s }, next_level
376
380
  )
377
- next_level.match("/:id/#{action}").to_route.name(:"#{action}_#{route_singular_name}")
381
+ next_level.match("/#{matched_keys}/#{action}").to_route.name(:"#{action}_#{route_singular_name}")
378
382
  end
379
383
  end
380
384
 
381
385
  if collection = options.delete(:collection)
382
386
  collection.each_pair do |action, methods|
383
387
  behaviors << Behavior.new(
384
- { :path => %r{^[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
385
- { :action => action.to_s }, next_level
388
+ { :path => %r{^[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
389
+ { :action => action.to_s }, next_level
386
390
  )
387
391
  next_level.match("/#{action}").to_route.name(:"#{action}_#{route_plural_name}")
388
392
  end
389
393
  end
390
394
 
391
- routes = many_behaviors_to(behaviors + next_level.send(:resources_behaviors), options)
395
+ routes = many_behaviors_to(behaviors + next_level.send(:resources_behaviors, matched_keys), options)
396
+
397
+
392
398
 
393
399
  # Add names to some routes
394
400
  [['', :"#{route_plural_name}"],
395
- ['/:id', :"#{route_singular_name}"],
396
- ['/new', :"new_#{route_singular_name}"],
397
- ['/:id/edit', :"edit_#{route_singular_name}"],
398
- ['/:id/delete', :"delete_#{route_singular_name}"]
401
+ ["/#{matched_keys}", :"#{route_singular_name}"],
402
+ ['/new', :"new_#{route_singular_name}"],
403
+ ["/#{matched_keys}/edit", :"edit_#{route_singular_name}"],
404
+ ["/#{matched_keys}/delete", :"delete_#{route_singular_name}"]
399
405
  ].each do |path,name|
400
406
  next_level.match(path).to_route.name(name)
401
407
  end
402
-
408
+
409
+
410
+ parent_keys = (matched_keys == ":id") ? ":#{singular}_id" : matched_keys
403
411
  if block_given?
404
412
  @@parent_resource.push(singular)
405
- yield next_level.match("/:#{singular}_id")
413
+ yield next_level.match("/#{parent_keys}")
406
414
  @@parent_resource.pop
407
415
  end
408
-
416
+
409
417
  routes
410
418
  end
411
419
 
@@ -438,6 +446,7 @@ module Merb
438
446
  # # GET /account/(\.:format)? :action => "show"
439
447
  # # GET /account/[;/]edit :action => "edit"
440
448
  # # PUT /account/(\.:format)? :action => "update"
449
+ # # GET /account/[;/]delete :action => "delete"
441
450
  # # DELETE /account/(\.:format)? :action => "destroy"
442
451
  #
443
452
  # You can optionally pass :namespace and :controller to refine the routing
@@ -590,22 +599,22 @@ module Merb
590
599
  end
591
600
 
592
601
  # ==== Parameters
593
- # parent<Merb::Router::Behavior>::
594
- # The parent behavior for the generated resource behaviors.
602
+ # matched_keys<String>::
603
+ # The keys to match
595
604
  #
596
605
  # ==== Returns
597
606
  # Array:: Behaviors for a RESTful resource.
598
- def resources_behaviors(parent = self)
607
+ def resources_behaviors(matched_keys = ":id")
599
608
  [
600
- Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :get }, { :action => "index" }, parent),
601
- Behavior.new({ :path => %r[^/index(\.:format)?$], :method => :get }, { :action => "index" }, parent),
602
- Behavior.new({ :path => %r[^/new$], :method => :get }, { :action => "new" }, parent),
603
- Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :post }, { :action => "create" }, parent),
604
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :get }, { :action => "show" }, parent),
605
- Behavior.new({ :path => %r[^/:id[;/]edit$], :method => :get }, { :action => "edit" }, parent),
606
- Behavior.new({ :path => %r[^/:id[;/]delete$], :method => :get }, { :action => "delete" }, parent),
607
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :put }, { :action => "update" }, parent),
608
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :delete }, { :action => "destroy" }, parent)
609
+ Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :get }, { :action => "index" }, self),
610
+ Behavior.new({ :path => %r[^/index(\.:format)?$], :method => :get }, { :action => "index" }, self),
611
+ Behavior.new({ :path => %r[^/new$], :method => :get }, { :action => "new" }, self),
612
+ Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :post }, { :action => "create" }, self),
613
+ Behavior.new({ :path => %r[^/#{matched_keys}(\.:format)?$], :method => :get }, { :action => "show" }, self),
614
+ Behavior.new({ :path => %r[^/#{matched_keys}[;/]edit$], :method => :get }, { :action => "edit" }, self),
615
+ Behavior.new({ :path => %r[^/#{matched_keys}[;/]delete$], :method => :get }, { :action => "delete" }, self),
616
+ Behavior.new({ :path => %r[^/#{matched_keys}(\.:format)?$], :method => :put }, { :action => "update" }, self),
617
+ Behavior.new({ :path => %r[^/#{matched_keys}(\.:format)?$], :method => :delete }, { :action => "destroy" }, self)
609
618
  ]
610
619
  end
611
620
 
@@ -17,6 +17,7 @@ module Merb
17
17
  def initialize(conditions, params, behavior = nil, &conditional_block)
18
18
  @conditions, @params, @behavior = conditions, params, behavior
19
19
  @conditional_block = conditional_block
20
+ @fixation=false
20
21
  if @behavior && (path = @behavior.merged_original_conditions[:path])
21
22
  @segments = segments_from_path(path)
22
23
  end
@@ -92,7 +93,7 @@ module Merb
92
93
  # ==== Returns
93
94
  # Boolean::
94
95
  # True if this route is a regexp, i.e. its behavior or one of the
95
- # behaviors ancestors is a regexp.
96
+ # behavior's ancestors is a regexp.
96
97
  def regexp?
97
98
  behavior.regexp? || behavior.send(:ancestors).any? { |a| a.regexp? }
98
99
  end
@@ -130,8 +131,12 @@ module Merb
130
131
  else
131
132
  raise "Segment type '#{segment.class}' can't be converted to a string"
132
133
  end
133
- (value.respond_to?(:to_param) ? value.to_param : value).to_s
134
+ (value.respond_to?(:to_param) ? value.to_param : value).to_s.unescape_regexp
134
135
  end.join
136
+ if query_params && format = query_params.delete(:format)
137
+ format = fallback[:format] if format == :current
138
+ url += ".#{format}"
139
+ end
135
140
  if query_params && !query_params.empty?
136
141
  url += "?" + Merb::Request.params_to_query_string(query_params)
137
142
  end
@@ -19,9 +19,8 @@ module Merb
19
19
  # has changed.
20
20
  def finalize_session
21
21
  new_session = request.session.read_cookie
22
-
23
22
  if @original_session != new_session
24
- set_cookie(_session_id_key, new_session, Time.now + _session_expiry)
23
+ cookies.set_cookie(_session_id_key, new_session, :expires => (Time.now + _session_expiry))
25
24
  end
26
25
  end
27
26
 
@@ -82,7 +81,7 @@ module Merb
82
81
  # ==== Raises
83
82
  # CookieOverflow:: Session contains too much information.
84
83
  def read_cookie
85
- unless @data.nil? or @data.empty?
84
+ unless @data.nil?
86
85
  updated = marshal(@data)
87
86
  raise CookieOverflow if updated.size > MAX
88
87
  updated
@@ -154,9 +153,10 @@ module Merb
154
153
  # Hash:: The stored session data.
155
154
  def unmarshal(cookie)
156
155
  if cookie
157
- data, digest = Merb::Request.unescape(cookie).split('--')
156
+ data, digest = cookie.split('--')
158
157
  return {} if data.blank?
159
158
  unless digest == generate_digest(data)
159
+ delete
160
160
  raise TamperedWithCookie, "Maybe the site's session_secret_key has changed?"
161
161
  end
162
162
  Marshal.load(Base64.decode64(data))
@@ -1,4 +1,3 @@
1
- require 'memcache_util'
2
1
  module Merb
3
2
 
4
3
  module SessionMixin #:nodoc:
@@ -19,7 +18,11 @@ module Merb
19
18
  # session has changed.
20
19
  def finalize_session
21
20
  if @_fingerprint != Marshal.dump(request.session.data).hash
22
- ::Cache.put("session:#{request.session.session_id}", request.session.data)
21
+ begin
22
+ CACHE.set("session:#{request.session.session_id}", request.session.data)
23
+ rescue => err
24
+ Merb.logger.debug("MemCache Error: #{err.message}")
25
+ end
23
26
  end
24
27
  set_cookie(_session_id_key, request.session.session_id, Time.now + _session_expiry) if (@_new_cookie || request.session.needs_new_cookie)
25
28
  end
@@ -34,7 +37,7 @@ module Merb
34
37
  ##
35
38
  # Sessions stored in memcached.
36
39
  #
37
- # Requires setup in your +init.rb+:
40
+ # Requires setup in your +init.rb+.
38
41
  #
39
42
  # require 'memcache'
40
43
  # CACHE = MemCache.new('127.0.0.1:11211', { :namespace => 'my_app' })
@@ -42,6 +45,12 @@ module Merb
42
45
  # And a setting in +init.rb+:
43
46
  #
44
47
  # c[:session_store] = 'memcache'
48
+ #
49
+ # If you are using the memcached gem instead of memcache-client, you must setup like this:
50
+ #
51
+ # require 'memcached'
52
+ # CACHE = Memcached.new('127.0.0.1:11211', { :namespace => 'my_app' })
53
+ #
45
54
  class MemCacheSession
46
55
 
47
56
  attr_accessor :session_id
@@ -75,7 +84,11 @@ module Merb
75
84
  # sessions matched session_id, a new MemCacheSession will be generated.
76
85
  def persist(session_id)
77
86
  unless session_id.blank?
78
- session = ::Cache.get("session:#{session_id}")
87
+ begin
88
+ session = CACHE.get("session:#{session_id}")
89
+ rescue => err
90
+ Merb.logger.debug("MemCache Error: #{err.message}")
91
+ end
79
92
  if session.nil?
80
93
  # Not in memcached, but assume that cookie exists
81
94
  session = new(session_id)
@@ -92,7 +105,6 @@ module Merb
92
105
  session_object.data = session
93
106
  [session_object, session_object.session_id]
94
107
  end
95
-
96
108
  end
97
109
 
98
110
  # Don't try to reload in dev mode.
@@ -161,7 +161,7 @@ module Merb
161
161
  # Close and remove the current log object.
162
162
  def close
163
163
  flush
164
- @log.close if @log.respond_to?(:close)
164
+ @log.close if @log.respond_to?(:close) && !@log.tty?
165
165
  @log = nil
166
166
  end
167
167
 
@@ -227,4 +227,4 @@ module Merb
227
227
 
228
228
  end
229
229
 
230
- end
230
+ end
@@ -1,5 +1,5 @@
1
1
  module Merb
2
-
2
+
3
3
  module Plugins
4
4
 
5
5
  # ==== Returns
@@ -9,17 +9,29 @@ module Merb
9
9
  def self.config
10
10
  @config ||= File.exists?(Merb.root / "config" / "plugins.yml") ? YAML.load(File.read(Merb.root / "config" / "plugins.yml")) || {} : {}
11
11
  end
12
-
12
+
13
13
  # ==== Returns
14
- # Array:: All Rakefiles for plugins.
14
+ # Array(String):: All Rakefile load paths Merb uses for plugins.
15
15
  def self.rakefiles
16
16
  Merb.rakefiles
17
17
  end
18
18
 
19
19
  # ==== Parameters
20
20
  # *rakefiles:: Rakefiles to add to the list of plugin Rakefiles.
21
+ #
22
+ # ==== Notes
23
+ #
24
+ # This is a recommended way to register your plugin's Raketasks
25
+ # in Merb.
26
+ #
27
+ # ==== Examples
28
+ # From merb_sequel plugin:
29
+ #
30
+ # if defined(Merb::Plugins)
31
+ # Merb::Plugins.add_rakefiles "merb_sequel" / "merbtasks"
32
+ # end
21
33
  def self.add_rakefiles(*rakefiles)
22
34
  Merb.add_rakefiles *rakefiles
23
35
  end
24
36
  end
25
- end
37
+ end
@@ -15,7 +15,10 @@ module Merb
15
15
  # :app:: The application
16
16
  def self.start(opts={})
17
17
  Merb.logger.warn!("Using Ebb adapter")
18
- ::Ebb.start_server(opts[:app], opts)
18
+ Merb::Dispatcher.use_mutex = false
19
+ th = Thread.new { ::Ebb.start_server(opts[:app], opts) }
20
+ Merb::Server.change_privilege
21
+ th.join
19
22
  end
20
23
  end
21
24
  end
@@ -15,7 +15,9 @@ module Merb
15
15
  # :app<String>>:: The application name.
16
16
  def self.start(opts={})
17
17
  Merb.logger.warn!("Using EventedMongrel adapter")
18
+ Merb::Dispatcher.use_mutex = false
18
19
  server = ::Mongrel::HttpServer.new(opts[:host], opts[:port].to_i)
20
+ Merb::Server.change_privilege
19
21
  server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
20
22
  server.run.join
21
23
  end
@@ -9,6 +9,7 @@ module Merb
9
9
  # :app<String>>:: The application name.
10
10
  def self.start(opts={})
11
11
  Merb.logger.warn!("Using FastCGI adapter")
12
+ Merb::Server.change_privilege
12
13
  ::Rack::Handler::FastCGI.run(opts[:app], opts)
13
14
  end
14
15
  end
@@ -17,6 +17,7 @@ module Merb
17
17
  def self.start(opts={})
18
18
  Merb.logger.warn!("Using Mongrel adapter")
19
19
  server = ::Mongrel::HttpServer.new(opts[:host], opts[:port].to_i)
20
+ Merb::Server.change_privilege
20
21
  server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
21
22
  server.run.join
22
23
  end
@@ -13,6 +13,7 @@ module Merb
13
13
  # If opts[:runner_code] matches a filename, that file will be read and
14
14
  # the contents executed. Otherwise the code will be executed directly.
15
15
  def self.start(opts={})
16
+ Merb::Server.change_privilege
16
17
  if opts[:runner_code]
17
18
  if File.exists?(opts[:runner_code])
18
19
  eval(File.read(opts[:runner_code]), TOPLEVEL_BINDING, __FILE__, __LINE__)
@@ -15,10 +15,12 @@ module Merb
15
15
  # :app<String>>:: The application name.
16
16
  def self.start(opts={})
17
17
  Merb.logger.warn!("Using Thin adapter")
18
+ Merb::Dispatcher.use_mutex = false
18
19
  if opts[:host].include?('/')
19
20
  opts[:host] = "#{opts[:host]}-#{opts[:port]}"
20
21
  end
21
- server = ::Thin::Server.new(opts[:host], opts[:port], opts[:app])
22
+ server = ::Thin::Server.start(opts[:host], opts[:port].to_i, opts[:app])
23
+ Merb::Server.change_privilege
22
24
  ::Thin::Logging.silent = true
23
25
  server.start!
24
26
  end
@@ -27,6 +27,7 @@ module Merb
27
27
  }
28
28
 
29
29
  server = ::WEBrick::HTTPServer.new(options)
30
+ Merb::Server.change_privilege
30
31
  server.mount("/", ::Rack::Handler::WEBrick, opts[:app])
31
32
  server.start
32
33
  end
@@ -12,7 +12,23 @@ module Merb
12
12
  @path_prefix = /^#{Regexp.escape(prefix)}/
13
13
  end
14
14
  end
15
-
15
+
16
+ # ==== Parameters
17
+ # env<Hash>:: Environment variables to pass on to the application.
18
+ #
19
+ # ==== Returns
20
+ # true or false::
21
+ def deferred?(env)
22
+ strip_path_prefix(env) if @path_prefix # Strip out the path_prefix if one was set
23
+ path = env['PATH_INFO'] ? env['PATH_INFO'].chomp('/') : ""
24
+ if path =~ Merb.deferred_actions
25
+ Merb.logger.info! "Deferring Request: #{path}"
26
+ true
27
+ else
28
+ false
29
+ end
30
+ end
31
+
16
32
  # ==== Parameters
17
33
  # env<Hash>:: Environment variables to pass on to the application.
18
34
  #