merb-core 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. data/CHANGELOG +136 -2
  2. data/CONTRIBUTORS +6 -0
  3. data/PUBLIC_CHANGELOG +38 -0
  4. data/Rakefile +38 -30
  5. data/lib/merb-core.rb +88 -23
  6. data/lib/merb-core/bootloader.rb +235 -51
  7. data/lib/merb-core/config.rb +121 -36
  8. data/lib/merb-core/controller/abstract_controller.rb +59 -36
  9. data/lib/merb-core/controller/exceptions.rb +2 -15
  10. data/lib/merb-core/controller/merb_controller.rb +44 -1
  11. data/lib/merb-core/controller/mime.rb +4 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +38 -21
  13. data/lib/merb-core/controller/mixins/render.rb +44 -29
  14. data/lib/merb-core/controller/mixins/responder.rb +3 -31
  15. data/lib/merb-core/controller/template.rb +45 -21
  16. data/lib/merb-core/core_ext/kernel.rb +60 -32
  17. data/lib/merb-core/dispatch/default_exception/default_exception.rb +2 -2
  18. data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +3 -1
  19. data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +71 -67
  20. data/lib/merb-core/dispatch/default_exception/views/index.html.erb +7 -3
  21. data/lib/merb-core/dispatch/dispatcher.rb +3 -3
  22. data/lib/merb-core/dispatch/request.rb +56 -9
  23. data/lib/merb-core/dispatch/router.rb +159 -133
  24. data/lib/merb-core/dispatch/router/behavior.rb +462 -703
  25. data/lib/merb-core/dispatch/router/cached_proc.rb +3 -3
  26. data/lib/merb-core/dispatch/router/resources.rb +289 -0
  27. data/lib/merb-core/dispatch/router/route.rb +514 -294
  28. data/lib/merb-core/dispatch/session.rb +4 -2
  29. data/lib/merb-core/logger.rb +213 -202
  30. data/lib/merb-core/plugins.rb +9 -1
  31. data/lib/merb-core/rack.rb +3 -1
  32. data/lib/merb-core/rack/adapter.rb +7 -4
  33. data/lib/merb-core/rack/adapter/abstract.rb +188 -0
  34. data/lib/merb-core/rack/adapter/ebb.rb +12 -13
  35. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -15
  36. data/lib/merb-core/rack/adapter/irb.rb +3 -2
  37. data/lib/merb-core/rack/adapter/mongrel.rb +22 -15
  38. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +4 -16
  39. data/lib/merb-core/rack/adapter/thin.rb +21 -22
  40. data/lib/merb-core/rack/adapter/thin_turbo.rb +4 -11
  41. data/lib/merb-core/rack/adapter/webrick.rb +54 -18
  42. data/lib/merb-core/rack/application.rb +4 -4
  43. data/lib/merb-core/rack/handler/mongrel.rb +12 -13
  44. data/lib/merb-core/rack/middleware/csrf.rb +1 -1
  45. data/lib/merb-core/rack/stream_wrapper.rb +41 -0
  46. data/lib/merb-core/server.rb +157 -90
  47. data/lib/merb-core/tasks/gem_management.rb +267 -0
  48. data/lib/merb-core/tasks/merb.rb +1 -0
  49. data/lib/merb-core/tasks/merb_rake_helper.rb +48 -34
  50. data/lib/merb-core/tasks/stats.rake +1 -1
  51. data/lib/merb-core/test.rb +9 -3
  52. data/lib/merb-core/test/helpers.rb +1 -0
  53. data/lib/merb-core/test/helpers/mock_request_helper.rb +393 -0
  54. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -2
  55. data/lib/merb-core/test/helpers/request_helper.rb +40 -372
  56. data/lib/merb-core/test/helpers/route_helper.rb +16 -2
  57. data/lib/merb-core/test/matchers.rb +1 -0
  58. data/lib/merb-core/test/matchers/controller_matchers.rb +4 -247
  59. data/lib/merb-core/test/matchers/request_matchers.rb +140 -0
  60. data/lib/merb-core/test/matchers/view_matchers.rb +22 -4
  61. data/lib/merb-core/test/run_specs.rb +118 -26
  62. data/lib/merb-core/test/test_ext/rspec.rb +181 -0
  63. data/lib/merb-core/version.rb +1 -9
  64. metadata +10 -342
  65. data/docs/bootloading.dox +0 -58
  66. data/docs/documentation_standards +0 -40
  67. data/docs/merb-core-call-stack-diagram.mmap +0 -0
  68. data/docs/merb-core-call-stack-diagram.pdf +0 -0
  69. data/docs/merb-core-call-stack-diagram.png +0 -0
  70. data/docs/new_render_api +0 -51
  71. data/lib/merb-core/vendor/facets.rb +0 -2
  72. data/lib/merb-core/vendor/facets/dictionary.rb +0 -433
  73. data/lib/merb-core/vendor/facets/inflect.rb +0 -342
  74. data/spec/private/config/adapter_spec.rb +0 -32
  75. data/spec/private/config/config_spec.rb +0 -202
  76. data/spec/private/config/environment_spec.rb +0 -13
  77. data/spec/private/config/merb_spec.rb +0 -34
  78. data/spec/private/config/spec_helper.rb +0 -1
  79. data/spec/private/core_ext/kernel_spec.rb +0 -159
  80. data/spec/private/dispatch/bootloader_spec.rb +0 -24
  81. data/spec/private/dispatch/fixture/app/controllers/application.rb +0 -4
  82. data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +0 -25
  83. data/spec/private/dispatch/fixture/app/controllers/foo.rb +0 -19
  84. data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +0 -8
  85. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +0 -37
  86. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +0 -216
  87. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +0 -38
  88. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +0 -40
  89. data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
  90. data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +0 -11
  91. data/spec/private/dispatch/fixture/config/black_hole.rb +0 -12
  92. data/spec/private/dispatch/fixture/config/environments/development.rb +0 -6
  93. data/spec/private/dispatch/fixture/config/environments/production.rb +0 -5
  94. data/spec/private/dispatch/fixture/config/environments/test.rb +0 -6
  95. data/spec/private/dispatch/fixture/config/init.rb +0 -45
  96. data/spec/private/dispatch/fixture/config/rack.rb +0 -11
  97. data/spec/private/dispatch/fixture/config/router.rb +0 -35
  98. data/spec/private/dispatch/fixture/log/merb_test.log +0 -8839
  99. data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
  100. data/spec/private/dispatch/fixture/public/merb.fcgi +0 -4
  101. data/spec/private/dispatch/fixture/public/stylesheets/master.css +0 -119
  102. data/spec/private/dispatch/route_params_spec.rb +0 -23
  103. data/spec/private/dispatch/spec_helper.rb +0 -1
  104. data/spec/private/router/behavior_spec.rb +0 -60
  105. data/spec/private/router/fixture/log/merb_test.log +0 -35
  106. data/spec/private/router/route_spec.rb +0 -418
  107. data/spec/private/router/router_spec.rb +0 -183
  108. data/spec/private/vendor/facets/plural_spec.rb +0 -564
  109. data/spec/private/vendor/facets/singular_spec.rb +0 -489
  110. data/spec/public/DEFINITIONS +0 -11
  111. data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +0 -1
  112. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +0 -1
  113. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +0 -1
  114. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +0 -1
  115. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +0 -1
  116. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +0 -1
  117. data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +0 -1
  118. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +0 -1
  119. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +0 -1
  120. data/spec/public/abstract_controller/controllers/cousins.rb +0 -41
  121. data/spec/public/abstract_controller/controllers/display.rb +0 -60
  122. data/spec/public/abstract_controller/controllers/filters.rb +0 -260
  123. data/spec/public/abstract_controller/controllers/helpers.rb +0 -41
  124. data/spec/public/abstract_controller/controllers/partial.rb +0 -121
  125. data/spec/public/abstract_controller/controllers/render.rb +0 -113
  126. data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +0 -1
  127. data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +0 -1
  128. data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +0 -1
  129. data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +0 -1
  130. data/spec/public/abstract_controller/controllers/views/layout/alt.erb +0 -1
  131. data/spec/public/abstract_controller/controllers/views/layout/custom.erb +0 -1
  132. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +0 -1
  133. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +0 -1
  134. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +0 -1
  135. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
  136. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +0 -1
  137. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +0 -1
  138. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +0 -1
  139. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +0 -1
  140. data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +0 -1
  141. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +0 -1
  142. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +0 -1
  143. data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +0 -1
  144. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +0 -1
  145. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +0 -1
  146. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +0 -1
  147. data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +0 -1
  148. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +0 -1
  149. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +0 -1
  150. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +0 -1
  151. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +0 -1
  152. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +0 -1
  153. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +0 -1
  154. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +0 -1
  155. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +0 -1
  156. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +0 -1
  157. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +0 -1
  158. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +0 -1
  159. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +0 -1
  160. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +0 -1
  161. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +0 -1
  162. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +0 -1
  163. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +0 -1
  164. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +0 -1
  165. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +0 -1
  166. data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +0 -1
  167. data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +0 -1
  168. data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +0 -1
  169. data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
  170. data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +0 -1
  171. data/spec/public/abstract_controller/display_spec.rb +0 -37
  172. data/spec/public/abstract_controller/filter_spec.rb +0 -136
  173. data/spec/public/abstract_controller/helper_spec.rb +0 -21
  174. data/spec/public/abstract_controller/partial_spec.rb +0 -61
  175. data/spec/public/abstract_controller/render_spec.rb +0 -90
  176. data/spec/public/abstract_controller/spec_helper.rb +0 -31
  177. data/spec/public/boot_loader/boot_loader_spec.rb +0 -33
  178. data/spec/public/boot_loader/spec_helper.rb +0 -1
  179. data/spec/public/controller/authentication_spec.rb +0 -174
  180. data/spec/public/controller/base_spec.rb +0 -88
  181. data/spec/public/controller/conditional_get_spec.rb +0 -100
  182. data/spec/public/controller/config/init.rb +0 -6
  183. data/spec/public/controller/controllers/authentication.rb +0 -74
  184. data/spec/public/controller/controllers/base.rb +0 -65
  185. data/spec/public/controller/controllers/conditional_get.rb +0 -35
  186. data/spec/public/controller/controllers/cookies.rb +0 -36
  187. data/spec/public/controller/controllers/dispatcher.rb +0 -35
  188. data/spec/public/controller/controllers/display.rb +0 -118
  189. data/spec/public/controller/controllers/redirect.rb +0 -36
  190. data/spec/public/controller/controllers/responder.rb +0 -93
  191. data/spec/public/controller/controllers/url.rb +0 -7
  192. data/spec/public/controller/controllers/views/layout/custom.html.erb +0 -1
  193. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +0 -1
  194. data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +0 -1
  195. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +0 -1
  196. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +0 -1
  197. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +0 -1
  198. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +0 -1
  199. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +0 -1
  200. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +0 -1
  201. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +0 -1
  202. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +0 -1
  203. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +0 -1
  204. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +0 -1
  205. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +0 -1
  206. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +0 -1
  207. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +0 -1
  208. data/spec/public/controller/cookies_spec.rb +0 -95
  209. data/spec/public/controller/dispatcher_spec.rb +0 -410
  210. data/spec/public/controller/display_spec.rb +0 -84
  211. data/spec/public/controller/redirect_spec.rb +0 -33
  212. data/spec/public/controller/responder_spec.rb +0 -169
  213. data/spec/public/controller/spec_helper.rb +0 -13
  214. data/spec/public/controller/url_spec.rb +0 -255
  215. data/spec/public/core/merb_core_spec.rb +0 -45
  216. data/spec/public/core_ext/fixtures/core_ext_dependency.rb +0 -2
  217. data/spec/public/core_ext/kernel_spec.rb +0 -88
  218. data/spec/public/core_ext/spec_helper.rb +0 -1
  219. data/spec/public/directory_structure/directory/app/controllers/application.rb +0 -3
  220. data/spec/public/directory_structure/directory/app/controllers/base.rb +0 -13
  221. data/spec/public/directory_structure/directory/app/controllers/custom.rb +0 -19
  222. data/spec/public/directory_structure/directory/app/views/base/template.html.erb +0 -1
  223. data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +0 -1
  224. data/spec/public/directory_structure/directory/config/router.rb +0 -3
  225. data/spec/public/directory_structure/directory/log/merb_test.log +0 -4588
  226. data/spec/public/directory_structure/directory_spec.rb +0 -43
  227. data/spec/public/logger/logger_spec.rb +0 -181
  228. data/spec/public/logger/spec_helper.rb +0 -1
  229. data/spec/public/rack/conditinal_get_middleware_spec.rb +0 -127
  230. data/spec/public/rack/csrf_middleware_spec.rb +0 -70
  231. data/spec/public/rack/rack_middleware_spec.rb +0 -99
  232. data/spec/public/rack/shared_example_groups.rb +0 -35
  233. data/spec/public/reloading/directory/app/controllers/application.rb +0 -3
  234. data/spec/public/reloading/directory/app/controllers/reload.rb +0 -6
  235. data/spec/public/reloading/directory/config/init.rb +0 -2
  236. data/spec/public/reloading/directory/log/merb_test.log +0 -288231
  237. data/spec/public/reloading/reload_spec.rb +0 -103
  238. data/spec/public/request/multipart_spec.rb +0 -41
  239. data/spec/public/request/request_spec.rb +0 -250
  240. data/spec/public/router/default_spec.rb +0 -21
  241. data/spec/public/router/deferred_spec.rb +0 -22
  242. data/spec/public/router/fixation_spec.rb +0 -49
  243. data/spec/public/router/fixture/log/merb_test.log +0 -524
  244. data/spec/public/router/namespace_spec.rb +0 -113
  245. data/spec/public/router/nested_matches_spec.rb +0 -97
  246. data/spec/public/router/nested_resources_spec.rb +0 -41
  247. data/spec/public/router/resource_spec.rb +0 -37
  248. data/spec/public/router/resources_spec.rb +0 -82
  249. data/spec/public/router/spec_helper.rb +0 -90
  250. data/spec/public/router/special_spec.rb +0 -61
  251. data/spec/public/router/string_spec.rb +0 -61
  252. data/spec/public/session/controllers/sessions.rb +0 -56
  253. data/spec/public/session/cookie_session_spec.rb +0 -73
  254. data/spec/public/session/memcached_session_spec.rb +0 -31
  255. data/spec/public/session/memory_session_spec.rb +0 -28
  256. data/spec/public/session/multiple_sessions_spec.rb +0 -74
  257. data/spec/public/session/no_session_spec.rb +0 -12
  258. data/spec/public/session/session_spec.rb +0 -106
  259. data/spec/public/template/template_spec.rb +0 -104
  260. data/spec/public/template/templates/error.html.erb +0 -2
  261. data/spec/public/template/templates/template.html.erb +0 -1
  262. data/spec/public/template/templates/template.html.myt +0 -1
  263. data/spec/public/test/controller_matchers_spec.rb +0 -412
  264. data/spec/public/test/controllers/controller_assertion_mock.rb +0 -7
  265. data/spec/public/test/controllers/dispatch_controller.rb +0 -11
  266. data/spec/public/test/controllers/spec_helper_controller.rb +0 -39
  267. data/spec/public/test/multipart_request_helper_spec.rb +0 -159
  268. data/spec/public/test/multipart_upload_text_file.txt +0 -1
  269. data/spec/public/test/request_helper_spec.rb +0 -269
  270. data/spec/public/test/route_helper_spec.rb +0 -78
  271. data/spec/public/test/route_matchers_spec.rb +0 -166
  272. data/spec/public/test/view_helper_spec.rb +0 -96
  273. data/spec/public/test/view_matchers_spec.rb +0 -183
  274. data/spec/spec_helper.rb +0 -121
@@ -227,7 +227,6 @@ class Merb::AbstractController
227
227
  def initialize(*args)
228
228
  @_benchmarks = {}
229
229
  @_caught_content = {}
230
- @_template_stack = []
231
230
  end
232
231
 
233
232
  # This will dispatch the request, calling internal before/after dispatch_callbacks
@@ -427,19 +426,13 @@ class Merb::AbstractController
427
426
  # ==== Alternatives
428
427
  # If a hash is used as the first argument, a default route will be
429
428
  # generated based on it and rparams.
430
- def url(name, rparams = {}, qparams = {})
431
- unless rparams.is_a?(Hash) || qparams.empty?
432
- rparams = qparams.merge(:id => rparams)
433
- end
434
- uri = Merb::Router.generate(name, rparams,
435
- { :controller => controller_name,
436
- :action => action_name,
437
- :format => params[:format]
438
- }
439
- )
440
- uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
441
- uri
429
+ # ====
430
+ # TODO: Update this documentation
431
+ def url(name, *args)
432
+ args << {}
433
+ Merb::Router.url(name, *args)
442
434
  end
435
+
443
436
  alias_method :relative_url, :url
444
437
 
445
438
  # ==== Parameters
@@ -458,30 +451,71 @@ class Merb::AbstractController
458
451
  # ==== Alternatives
459
452
  # If a hash is used as the first argument, a default route will be
460
453
  # generated based on it and rparams.
461
- def absolute_url(name, rparams={})
454
+ def absolute_url(name, *args)
462
455
  # FIXME: arrgh, why request.protocol returns http://?
463
456
  # :// is not part of protocol name
464
- if rparams.is_a?(Hash)
465
- protocol = rparams.delete(:protocol)
466
- protocol << "://" if protocol
467
- host = rparams.delete(:host)
468
- end
457
+ options = extract_options_from_args!(args) || {}
458
+ protocol = options.delete(:protocol)
459
+ host = options.delete(:host)
469
460
 
470
- (protocol || request.protocol) +
471
- (host || request.host) +
472
- url(name, rparams)
461
+ raise ArgumentError, "The :protocol option must be specified" unless protocol
462
+ raise ArgumentError, "The :host option must be specified" unless host
463
+
464
+ args << options
465
+
466
+ protocol + "://" + host + url(name, *args)
467
+ end
468
+
469
+ # Generates a URL for a single or nested resource.
470
+ #
471
+ # ==== Parameters
472
+ # resources<Symbol,Object>:: The resources for which the URL
473
+ # should be generated. These resources should be specified
474
+ # in the router.rb file using #resources and #resource.
475
+ #
476
+ # options<Hash>:: Any extra parameters that are needed to
477
+ # generate the URL.
478
+ #
479
+ # ==== Returns
480
+ # String:: The generated URL.
481
+ #
482
+ # ==== Examples
483
+ #
484
+ # Merb::Router.prepare do
485
+ # resources :users do
486
+ # resources :comments
487
+ # end
488
+ # end
489
+ #
490
+ # resource(:users) # => /users
491
+ # resource(@user) # => /users/10
492
+ # resource(@user, :comments) # => /users/10/comments
493
+ # resource(@user, @comment) # => /users/10/comments/15
494
+ # resource(:users, :new) # => /users/new
495
+ # resource(:@user, :edit) # => /users/10/edit
496
+ #
497
+ def resource(*args)
498
+ args << params
499
+ Merb::Router.resource(*args)
473
500
  end
474
501
 
475
502
  # Calls the capture method for the selected template engine.
476
503
  #
477
504
  # ==== Parameters
478
505
  # *args:: Arguments to pass to the block.
479
- # &block:: The template block to call.
506
+ # &block:: The block to call.
480
507
  #
481
508
  # ==== Returns
482
- # String:: The output of the block.
509
+ # String:: The output of a template block or the return value of a non-template block converted to a string.
483
510
  def capture(*args, &block)
484
- send("capture_#{@_engine}", *args, &block)
511
+ ret = nil
512
+
513
+ captured = send("capture_#{@_engine}", *args) do |*args|
514
+ ret = yield *args
515
+ end
516
+
517
+ # return captured value only if it is not empty
518
+ captured.empty? ? ret.to_s : captured
485
519
  end
486
520
 
487
521
  # Calls the concatenate method for the selected template engine.
@@ -571,15 +605,4 @@ class Merb::AbstractController
571
605
  opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
572
606
  return opts
573
607
  end
574
-
575
- # Attempts to return the partial local variable corresponding to sym.
576
- #
577
- # ==== Paramteres
578
- # sym<Symbol>:: Method name.
579
- # *arg:: Arguments to pass to the method.
580
- # &blk:: A block to pass to the method.
581
- def method_missing(sym, *args, &blk)
582
- return @_merb_partial_locals[sym] if @_merb_partial_locals && @_merb_partial_locals.key?(sym)
583
- super
584
- end
585
608
  end
@@ -278,6 +278,8 @@ module Merb
278
278
 
279
279
  class ServerError < Merb::ControllerExceptions::Base; end
280
280
 
281
+ class InternalServerError < Merb::ControllerExceptions::ServerError; self.status = 500; end
282
+
281
283
  class NotImplemented < Merb::ControllerExceptions::ServerError; self.status = 501; end
282
284
 
283
285
  class BadGateway < Merb::ControllerExceptions::ServerError; self.status = 502; end
@@ -287,21 +289,6 @@ module Merb
287
289
  class GatewayTimeout < Merb::ControllerExceptions::ServerError; self.status = 504; end
288
290
 
289
291
  class HTTPVersionNotSupported < Merb::ControllerExceptions::ServerError; self.status = 505; end
290
-
291
- class InternalServerError < Merb::ControllerExceptions::ServerError #:doc:
292
- self.status = 500;
293
- def initialize(exception = nil)
294
- @exception = exception
295
- end
296
-
297
- def backtrace
298
- @exception ? @exception.backtrace : backtrace
299
- end
300
-
301
- def message
302
- @exception ? @exception.message : message
303
- end
304
- end
305
292
  end
306
293
 
307
294
  # Required to show exceptions in the log file
@@ -218,6 +218,33 @@ class Merb::Controller < Merb::AbstractController
218
218
  # ==== Returns
219
219
  # Hash:: The parameters from the request object
220
220
  def params() request.params end
221
+
222
+ # ==== Parameters
223
+ # name<~to_sym, Hash>:: The name of the URL to generate.
224
+ # rparams<Hash>:: Parameters for the route generation.
225
+ #
226
+ # ==== Returns
227
+ # String:: The generated URL.
228
+ #
229
+ # ==== Alternatives
230
+ # If a hash is used as the first argument, a default route will be
231
+ # generated based on it and rparams.
232
+ # ====
233
+ # TODO: Update this documentation
234
+ def url(name, *args)
235
+ args << params
236
+ Merb::Router.url(name, *args)
237
+ end
238
+
239
+ alias_method :relative_url, :url
240
+
241
+ def absolute_url(*args)
242
+ options = extract_options_from_args!(args) || {}
243
+ options[:protocol] ||= request.protocol
244
+ options[:host] ||= request.host
245
+ args << options
246
+ super(args.first, *args[1..-1])
247
+ end
221
248
 
222
249
  # The results of the controller's render, to be returned to Rack.
223
250
  #
@@ -225,7 +252,23 @@ class Merb::Controller < Merb::AbstractController
225
252
  # Array[Integer, Hash, String]::
226
253
  # The controller's status code, headers, and body
227
254
  def rack_response
228
- [status, headers, body]
255
+ [status, headers, Merb::Rack::StreamWrapper.new(body)]
256
+ end
257
+
258
+ # Sets a controller to be "abstract"
259
+ # This controller will not be able to be routed to
260
+ # and is used for super classing only
261
+ def self.abstract!
262
+ @_abstract = true
263
+ end
264
+
265
+ # Asks a controller if it is abstract
266
+ #
267
+ # === Returns
268
+ # Boolean
269
+ # true if the controller has been set as abstract
270
+ def self.abstract?
271
+ !!@_abstract
229
272
  end
230
273
 
231
274
  # Hide any methods that may have been exposed as actions before.
@@ -7,6 +7,10 @@ module Merb
7
7
  ResponderMixin::TYPES
8
8
  end
9
9
 
10
+ def available_accepts
11
+ ResponderMixin::MIMES
12
+ end
13
+
10
14
  # Any specific outgoing headers should be included here. These are not
11
15
  # the content-type header but anything in addition to it.
12
16
  # +transform_method+ should be set to a symbol of the method used to
@@ -62,6 +62,7 @@ module Merb
62
62
  # ==== Parameters
63
63
  # data<String>:: a chunk of data to return.
64
64
  def send_chunk(data)
65
+ only_runs_on_mongrel!
65
66
  @response.write('%x' % data.size + "\r\n")
66
67
  @response.write(data + "\r\n")
67
68
  end
@@ -76,12 +77,8 @@ module Merb
76
77
  # A block that Mongrel can call later, allowing Merb to release the
77
78
  # thread lock and render another request.
78
79
  def render_deferred(&blk)
79
- must_support_streaming!
80
80
  Proc.new {|response|
81
- result = blk.call
82
- response.send_status(result.length)
83
- response.send_header
84
- response.write(result)
81
+ response.write(blk.call)
85
82
  }
86
83
  end
87
84
 
@@ -96,10 +93,7 @@ module Merb
96
93
  # Proc::
97
94
  # A block that Mongrel can call after returning the string to the user.
98
95
  def render_then_call(str, &blk)
99
- must_support_streaming!
100
96
  Proc.new {|response|
101
- response.send_status(str.length)
102
- response.send_header
103
97
  response.write(str)
104
98
  blk.call
105
99
  }
@@ -166,7 +160,13 @@ module Merb
166
160
  'Content-Disposition' => disposition,
167
161
  'Content-Transfer-Encoding' => 'binary'
168
162
  )
169
- File.open(file, 'rb')
163
+ Proc.new {|response|
164
+ file = File.open(file, 'rb')
165
+ while chunk = file.read(16384)
166
+ response.write chunk
167
+ end
168
+ file.close
169
+ }
170
170
  end
171
171
 
172
172
  # Send binary data over HTTP to the user as a file download. May set content type,
@@ -217,7 +217,6 @@ module Merb
217
217
  # end
218
218
  # end
219
219
  def stream_file(opts={}, &stream)
220
- must_support_streaming!
221
220
  opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
222
221
  disposition = opts[:disposition].dup || 'attachment'
223
222
  disposition << %(; filename="#{opts[:filename]}")
@@ -229,8 +228,6 @@ module Merb
229
228
  'CONTENT-LENGTH' => opts[:content_length].to_s
230
229
  )
231
230
  Proc.new{|response|
232
- response.send_status(opts[:content_length])
233
- response.send_header
234
231
  stream.call(response)
235
232
  }
236
233
  end
@@ -239,10 +236,30 @@ module Merb
239
236
  # from nginx. For more information, see the nginx wiki:
240
237
  # http://wiki.codemongers.com/NginxXSendfile
241
238
  #
239
+ # and the following sample gist:
240
+ # http://gist.github.com/11225
241
+ #
242
+ # there's also example application up on GitHub:
243
+ #
244
+ # http://github.com/michaelklishin/nginx-x-accel-redirect-example-application/tree/master
245
+ #
246
+ # Unless Content-Disposition is set before calling this method,
247
+ # it is set to attachment with streamed file name.
248
+ #
242
249
  # ==== Parameters
243
- # file<String>:: Path to file to send to the client.
244
- def nginx_send_file(file)
245
- headers['X-Accel-Redirect'] = file
250
+ # path<String>:: Path to file to send to the client.
251
+ # content_type<String>:: content type header value. By default is set to empty string to let
252
+ # Nginx detect it.
253
+ #
254
+ # ==== Return
255
+ # One space string.
256
+ def nginx_send_file(path, content_type = "")
257
+ # Let Nginx detect content type unless it is explicitly set
258
+ headers['Content-Type'] = content_type
259
+ headers["Content-Disposition"] ||= "attachment; filename=#{path.split('/').last}"
260
+
261
+ headers['X-Accel-Redirect'] = path
262
+
246
263
  return ' '
247
264
  end
248
265
 
@@ -283,16 +300,16 @@ module Merb
283
300
  Erubis::XmlHelper.escape_xml(obj.to_s)
284
301
  end
285
302
  alias h escape_xml
286
- alias html_escape escape_xml
303
+ alias escape_html escape_xml
287
304
 
288
305
  private
289
- # Checks whether streaming is supported by the current Rack adapter.
306
+ # Marks an output method that only runs on the mongrel webserver.
290
307
  #
291
308
  # ==== Raises
292
- # NotImplemented:: The Rack adapter doens't support streaming.
293
- def must_support_streaming!
294
- unless request.env['rack.streaming']
295
- raise(Merb::ControllerExceptions::NotImplemented, "Current Rack adapter does not support streaming")
309
+ # NotImplemented:: The Rack adapter is not mongrel.
310
+ def only_runs_on_mongrel!
311
+ unless Merb::Config[:log_stream] == 'mongrel'
312
+ raise(Merb::ControllerExceptions::NotImplemented, "Current Rack adapter is not mongrel. cannot support this feature")
296
313
  end
297
314
  end
298
315
  end
@@ -268,17 +268,6 @@ module Merb::RenderMixin
268
268
  #
269
269
  # In this case, "one" will be available in the partial through the local
270
270
  # variable named +number+.
271
- #
272
- # ==== Notes
273
- # It is important to note that the object being passed to the partial
274
- # as well as any extra local variables cannot use names of helper methods
275
- # since any helper method of the same name will take precedence over the
276
- # passed variable. Example:
277
- #
278
- # partial :bar, :with => "one", :as => :partial
279
- #
280
- # In this case, "one" will not be available in the partial because "partial"
281
- # is already a helper method.
282
271
  def partial(template, opts={})
283
272
 
284
273
  # partial :foo becomes "#{controller_name}/_foo"
@@ -290,32 +279,36 @@ module Merb::RenderMixin
290
279
  kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name
291
280
  template = "_#{File.basename(template)}"
292
281
  end
293
- template_method, template_location =
294
- _template_for(template, opts.delete(:format) || content_type, kontroller, template_path)
295
282
 
296
- (@_old_partial_locals ||= []).push @_merb_partial_locals
297
-
298
283
  # This handles no :with as well
299
284
  with = [opts.delete(:with)].flatten
300
- as = opts.delete(:as) || template_location.match(%r[.*/_([^\.]*)])[1]
301
-
302
- @_merb_partial_locals = opts.merge(:collection_index => -1, :collection_size => with.size)
285
+ as = (opts.delete(:as) || template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym
286
+
287
+ # Ensure that as is in the locals hash even if it isn't passed in here
288
+ # so that it's included in the preamble.
289
+ locals = opts.merge(:collection_index => -1, :collection_size => with.size, as => opts[as])
290
+ template_method, template_location = _template_for(
291
+ template,
292
+ opts.delete(:format) || content_type,
293
+ kontroller,
294
+ template_path,
295
+ locals.keys)
303
296
 
304
297
  # this handles an edge-case where the name of the partial is _foo.* and your opts
305
298
  # have :foo as a key.
306
- named_local = @_merb_partial_locals.key?(as.to_sym)
299
+ named_local = opts.key?(as)
307
300
 
308
301
  sent_template = with.map do |temp|
309
- @_merb_partial_locals[as.to_sym] = temp unless named_local
302
+ locals[as] = temp unless named_local
303
+
310
304
  if template_method && self.respond_to?(template_method)
311
- @_merb_partial_locals[:collection_index] += 1
312
- send(template_method)
305
+ locals[:collection_index] += 1
306
+ send(template_method, locals)
313
307
  else
314
308
  raise TemplateNotFound, "Could not find template at #{template_location}.*"
315
309
  end
316
310
  end.join
317
311
 
318
- @_merb_partial_locals = @_old_partial_locals.pop
319
312
  sent_template
320
313
  end
321
314
 
@@ -382,6 +375,7 @@ module Merb::RenderMixin
382
375
  # context<Object>:: The controller action or template (basename or absolute path).
383
376
  # content_type<~to_s>:: The content type (like html or json).
384
377
  # controller<~to_s>:: The name of the controller. Defaults to nil.
378
+ # locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
385
379
  #
386
380
  # ==== Options (opts)
387
381
  # :template<String>::
@@ -391,13 +385,13 @@ module Merb::RenderMixin
391
385
  # ==== Returns
392
386
  # Array[Symbol, String]::
393
387
  # A pair consisting of the template method and location.
394
- def _template_for(context, content_type, controller=nil, template=nil)
388
+ def _template_for(context, content_type, controller=nil, template=nil, locals=[])
395
389
  template_method, template_location = nil, nil
396
390
 
397
391
  # absolute path to a template (:template => "/foo/bar")
398
392
  if template.is_a?(String) && template =~ %r{^/}
399
393
  template_location = self._absolute_template_location(template, content_type)
400
- return [_template_method_for(template_location), template_location]
394
+ return [_template_method_for(template_location, locals), template_location]
401
395
  end
402
396
 
403
397
  self.class._template_roots.reverse_each do |root, template_meth|
@@ -409,7 +403,7 @@ module Merb::RenderMixin
409
403
  template_location = root / self.send(template_meth, context, content_type, controller)
410
404
  end
411
405
 
412
- break if template_method = _template_method_for(template_location.to_s)
406
+ break if template_method = _template_method_for(template_location.to_s, locals)
413
407
  end
414
408
 
415
409
  # template_location is a Pathname
@@ -421,11 +415,12 @@ module Merb::RenderMixin
421
415
  #
422
416
  # ==== Parameters
423
417
  # template_location<String>:: The phyical path of the template
418
+ # locals<Array[Symbol]>:: A list of locals to assign from the args passed into the compiled template.
424
419
  #
425
420
  # ==== Returns
426
421
  # String:: The method, if it exists. Otherwise return nil.
427
- def _template_method_for(template_location)
428
- meth = Merb::Template.template_for(template_location)
422
+ def _template_method_for(template_location, locals)
423
+ meth = Merb::Template.template_for(template_location, [], locals)
429
424
  meth && self.respond_to?(meth) ? meth : nil
430
425
  end
431
426
 
@@ -439,7 +434,7 @@ module Merb::RenderMixin
439
434
  #---
440
435
  # @public
441
436
  def catch_content(obj = :for_layout)
442
- @_caught_content[obj] * '' unless @_caught_content[obj].nil?
437
+ @_caught_content[obj] || ''
443
438
  end
444
439
 
445
440
  # Called in templates to test for the existence of previously thrown content.
@@ -474,6 +469,26 @@ module Merb::RenderMixin
474
469
  unless string || block_given?
475
470
  raise ArgumentError, "You must pass a block or a string into throw_content"
476
471
  end
472
+ @_caught_content[obj] = string.to_s << (block_given? ? capture(&block) : "")
473
+ end
474
+
475
+ # Called in templates to append content for later use. Works like throw_content.
476
+ #
477
+ # @param [Object] obj
478
+ # Key used in the thrown_content hash.
479
+ # @param [String] string
480
+ # Textual content. Default to nil.
481
+ # @yield
482
+ # Evaluated with result concatenated to string.
483
+ #
484
+ # @raise [ArgumentError]
485
+ # Neither string nor block given
486
+ #
487
+ # @api public
488
+ def append_content(obj, string = nil, &block)
489
+ unless string || block_given?
490
+ raise ArgumentError, "You must pass a block or a string into append_content"
491
+ end
477
492
  @_caught_content[obj] = [] if @_caught_content[obj].nil?
478
493
  @_caught_content[obj] << string.to_s << (block_given? ? capture(&block) : "")
479
494
  end