merb-core 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
  #