thorero 0.9.4.4 → 0.9.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. data/LICENSE +1 -1
  2. data/README +21 -0
  3. data/Rakefile +275 -108
  4. data/TODO +0 -0
  5. data/bin/merb +12 -0
  6. data/bin/merb-specs +5 -0
  7. data/docs/bootloading.dox +58 -0
  8. data/docs/documentation_standards +40 -0
  9. data/docs/merb-core-call-stack-diagram.mmap +0 -0
  10. data/docs/merb-core-call-stack-diagram.pdf +0 -0
  11. data/docs/merb-core-call-stack-diagram.png +0 -0
  12. data/docs/new_render_api +51 -0
  13. data/lib/merb-core.rb +603 -0
  14. data/lib/merb-core/autoload.rb +32 -0
  15. data/lib/merb-core/bootloader.rb +708 -0
  16. data/lib/merb-core/config.rb +303 -0
  17. data/lib/merb-core/constants.rb +43 -0
  18. data/lib/merb-core/controller/abstract_controller.rb +578 -0
  19. data/lib/merb-core/controller/exceptions.rb +302 -0
  20. data/lib/merb-core/controller/merb_controller.rb +256 -0
  21. data/lib/merb-core/controller/mime.rb +106 -0
  22. data/lib/merb-core/controller/mixins/authentication.rb +87 -0
  23. data/lib/merb-core/controller/mixins/controller.rb +290 -0
  24. data/lib/merb-core/controller/mixins/render.rb +481 -0
  25. data/lib/merb-core/controller/mixins/responder.rb +472 -0
  26. data/lib/merb-core/controller/template.rb +254 -0
  27. data/lib/merb-core/core_ext.rb +8 -0
  28. data/lib/merb-core/core_ext/kernel.rb +319 -0
  29. data/lib/merb-core/dispatch/cookies.rb +91 -0
  30. data/lib/merb-core/dispatch/dispatcher.rb +278 -0
  31. data/lib/merb-core/dispatch/exceptions.html.erb +303 -0
  32. data/lib/merb-core/dispatch/request.rb +603 -0
  33. data/lib/merb-core/dispatch/router.rb +179 -0
  34. data/lib/merb-core/dispatch/router/behavior.rb +867 -0
  35. data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
  36. data/lib/merb-core/dispatch/router/route.rb +321 -0
  37. data/lib/merb-core/dispatch/session.rb +78 -0
  38. data/lib/merb-core/dispatch/session/cookie.rb +168 -0
  39. data/lib/merb-core/dispatch/session/memcached.rb +184 -0
  40. data/lib/merb-core/dispatch/session/memory.rb +241 -0
  41. data/lib/merb-core/dispatch/worker.rb +28 -0
  42. data/lib/merb-core/gem_ext/erubis.rb +77 -0
  43. data/lib/{extlib → merb-core}/logger.rb +2 -2
  44. data/lib/merb-core/plugins.rb +59 -0
  45. data/lib/merb-core/rack.rb +21 -0
  46. data/lib/merb-core/rack/adapter.rb +44 -0
  47. data/lib/merb-core/rack/adapter/ebb.rb +25 -0
  48. data/lib/merb-core/rack/adapter/evented_mongrel.rb +26 -0
  49. data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
  50. data/lib/merb-core/rack/adapter/irb.rb +118 -0
  51. data/lib/merb-core/rack/adapter/mongrel.rb +26 -0
  52. data/lib/merb-core/rack/adapter/runner.rb +28 -0
  53. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
  54. data/lib/merb-core/rack/adapter/thin.rb +39 -0
  55. data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
  56. data/lib/merb-core/rack/adapter/webrick.rb +36 -0
  57. data/lib/merb-core/rack/application.rb +18 -0
  58. data/lib/merb-core/rack/handler/mongrel.rb +97 -0
  59. data/lib/merb-core/rack/middleware.rb +26 -0
  60. data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
  61. data/lib/merb-core/rack/middleware/profiler.rb +19 -0
  62. data/lib/merb-core/rack/middleware/static.rb +45 -0
  63. data/lib/merb-core/server.rb +252 -0
  64. data/lib/merb-core/tasks/audit.rake +68 -0
  65. data/lib/merb-core/tasks/merb.rb +1 -0
  66. data/lib/merb-core/tasks/merb_rake_helper.rb +12 -0
  67. data/lib/merb-core/test.rb +11 -0
  68. data/lib/merb-core/test/helpers.rb +9 -0
  69. data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
  70. data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
  71. data/lib/merb-core/test/helpers/request_helper.rb +344 -0
  72. data/lib/merb-core/test/helpers/route_helper.rb +33 -0
  73. data/lib/merb-core/test/helpers/view_helper.rb +121 -0
  74. data/lib/merb-core/test/matchers.rb +9 -0
  75. data/lib/merb-core/test/matchers/controller_matchers.rb +319 -0
  76. data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
  77. data/lib/merb-core/test/matchers/view_matchers.rb +335 -0
  78. data/lib/merb-core/test/run_specs.rb +47 -0
  79. data/lib/merb-core/test/tasks/spectasks.rb +68 -0
  80. data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
  81. data/lib/merb-core/test/test_ext/object.rb +14 -0
  82. data/lib/merb-core/test/test_ext/string.rb +14 -0
  83. data/lib/merb-core/vendor/facets.rb +2 -0
  84. data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
  85. data/lib/merb-core/vendor/facets/inflect.rb +345 -0
  86. data/lib/merb-core/version.rb +11 -0
  87. data/spec/private/config/adapter_spec.rb +32 -0
  88. data/spec/private/config/config_spec.rb +202 -0
  89. data/spec/private/config/environment_spec.rb +13 -0
  90. data/spec/private/config/spec_helper.rb +1 -0
  91. data/spec/private/core_ext/kernel_spec.rb +169 -0
  92. data/spec/private/dispatch/bootloader_spec.rb +24 -0
  93. data/spec/private/dispatch/cookies_spec.rb +107 -0
  94. data/spec/private/dispatch/dispatch_spec.rb +35 -0
  95. data/spec/private/dispatch/fixture/app/controllers/application.rb +4 -0
  96. data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +27 -0
  97. data/spec/private/dispatch/fixture/app/controllers/foo.rb +21 -0
  98. data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +8 -0
  99. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +37 -0
  100. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
  101. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
  102. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +40 -0
  103. data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
  104. data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +11 -0
  105. data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
  106. data/spec/private/dispatch/fixture/config/environments/development.rb +6 -0
  107. data/spec/private/dispatch/fixture/config/environments/production.rb +5 -0
  108. data/spec/private/dispatch/fixture/config/environments/test.rb +6 -0
  109. data/spec/private/dispatch/fixture/config/init.rb +45 -0
  110. data/spec/private/dispatch/fixture/config/rack.rb +11 -0
  111. data/spec/private/dispatch/fixture/config/router.rb +35 -0
  112. data/spec/private/dispatch/fixture/log/merb_test.log +1874 -0
  113. data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
  114. data/spec/private/dispatch/fixture/public/merb.fcgi +4 -0
  115. data/spec/private/dispatch/fixture/public/stylesheets/master.css +119 -0
  116. data/spec/private/dispatch/route_params_spec.rb +24 -0
  117. data/spec/private/dispatch/session_mixin_spec.rb +47 -0
  118. data/spec/private/dispatch/spec_helper.rb +1 -0
  119. data/spec/private/plugins/plugin_spec.rb +166 -0
  120. data/spec/private/rack/application_spec.rb +49 -0
  121. data/spec/private/router/behavior_spec.rb +60 -0
  122. data/spec/private/router/fixture/log/merb_test.log +139 -0
  123. data/spec/private/router/route_spec.rb +414 -0
  124. data/spec/private/router/router_spec.rb +175 -0
  125. data/spec/private/vendor/facets/plural_spec.rb +564 -0
  126. data/spec/private/vendor/facets/singular_spec.rb +489 -0
  127. data/spec/public/DEFINITIONS +11 -0
  128. data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +1 -0
  129. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +1 -0
  130. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +1 -0
  131. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +1 -0
  132. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +1 -0
  133. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  134. data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +1 -0
  135. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +1 -0
  136. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +1 -0
  137. data/spec/public/abstract_controller/controllers/cousins.rb +41 -0
  138. data/spec/public/abstract_controller/controllers/display.rb +54 -0
  139. data/spec/public/abstract_controller/controllers/filters.rb +193 -0
  140. data/spec/public/abstract_controller/controllers/helpers.rb +41 -0
  141. data/spec/public/abstract_controller/controllers/partial.rb +121 -0
  142. data/spec/public/abstract_controller/controllers/render.rb +113 -0
  143. data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +1 -0
  144. data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +1 -0
  145. data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +1 -0
  146. data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +1 -0
  147. data/spec/public/abstract_controller/controllers/views/layout/alt.erb +1 -0
  148. data/spec/public/abstract_controller/controllers/views/layout/custom.erb +1 -0
  149. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +1 -0
  150. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +1 -0
  151. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +1 -0
  152. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
  153. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +1 -0
  154. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  155. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +1 -0
  156. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +1 -0
  157. data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +1 -0
  158. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +1 -0
  159. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +1 -0
  160. data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +1 -0
  161. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +1 -0
  162. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +1 -0
  163. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +1 -0
  164. data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +1 -0
  165. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +1 -0
  166. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +1 -0
  167. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +1 -0
  168. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +1 -0
  169. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +1 -0
  170. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +1 -0
  171. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +1 -0
  172. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +1 -0
  173. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +1 -0
  174. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +1 -0
  175. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +1 -0
  176. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +1 -0
  177. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +1 -0
  178. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +1 -0
  179. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +1 -0
  180. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +1 -0
  181. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +1 -0
  182. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +1 -0
  183. data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +1 -0
  184. data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +1 -0
  185. data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +1 -0
  186. data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
  187. data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +1 -0
  188. data/spec/public/abstract_controller/display_spec.rb +33 -0
  189. data/spec/public/abstract_controller/filter_spec.rb +106 -0
  190. data/spec/public/abstract_controller/helper_spec.rb +21 -0
  191. data/spec/public/abstract_controller/partial_spec.rb +61 -0
  192. data/spec/public/abstract_controller/render_spec.rb +90 -0
  193. data/spec/public/abstract_controller/spec_helper.rb +31 -0
  194. data/spec/public/boot_loader/boot_loader_spec.rb +33 -0
  195. data/spec/public/boot_loader/spec_helper.rb +1 -0
  196. data/spec/public/controller/authentication_spec.rb +103 -0
  197. data/spec/public/controller/base_spec.rb +36 -0
  198. data/spec/public/controller/controllers/authentication.rb +45 -0
  199. data/spec/public/controller/controllers/base.rb +36 -0
  200. data/spec/public/controller/controllers/display.rb +118 -0
  201. data/spec/public/controller/controllers/redirect.rb +30 -0
  202. data/spec/public/controller/controllers/responder.rb +93 -0
  203. data/spec/public/controller/controllers/url.rb +7 -0
  204. data/spec/public/controller/controllers/views/layout/custom.html.erb +1 -0
  205. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
  206. data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +1 -0
  207. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +1 -0
  208. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +1 -0
  209. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +1 -0
  210. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +1 -0
  211. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +1 -0
  212. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +1 -0
  213. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
  214. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +1 -0
  215. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +1 -0
  216. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +1 -0
  217. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +1 -0
  218. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +1 -0
  219. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +1 -0
  220. data/spec/public/controller/display_spec.rb +84 -0
  221. data/spec/public/controller/redirect_spec.rb +27 -0
  222. data/spec/public/controller/responder_spec.rb +163 -0
  223. data/spec/public/controller/spec_helper.rb +11 -0
  224. data/spec/public/controller/url_spec.rb +180 -0
  225. data/spec/public/core/merb_core_spec.rb +45 -0
  226. data/spec/public/core_ext/class_spec.rb +91 -0
  227. data/spec/public/core_ext/fixtures/core_ext_dependency.rb +2 -0
  228. data/spec/public/core_ext/kernel_spec.rb +9 -0
  229. data/spec/public/core_ext/spec_helper.rb +1 -0
  230. data/spec/public/directory_structure/directory/app/controllers/application.rb +3 -0
  231. data/spec/public/directory_structure/directory/app/controllers/base.rb +13 -0
  232. data/spec/public/directory_structure/directory/app/controllers/custom.rb +19 -0
  233. data/spec/public/directory_structure/directory/app/views/base/template.html.erb +1 -0
  234. data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +1 -0
  235. data/spec/public/directory_structure/directory/config/router.rb +3 -0
  236. data/spec/public/directory_structure/directory/log/merb_test.log +562 -0
  237. data/spec/public/directory_structure/directory_spec.rb +44 -0
  238. data/spec/public/logger/logger_spec.rb +181 -0
  239. data/spec/public/logger/spec_helper.rb +1 -0
  240. data/spec/public/reloading/directory/app/controllers/application.rb +3 -0
  241. data/spec/public/reloading/directory/app/controllers/reload.rb +6 -0
  242. data/spec/public/reloading/directory/config/init.rb +2 -0
  243. data/spec/public/reloading/directory/log/merb_test.log +138 -0
  244. data/spec/public/reloading/reload_spec.rb +103 -0
  245. data/spec/public/request/multipart_spec.rb +41 -0
  246. data/spec/public/request/request_spec.rb +228 -0
  247. data/spec/public/router/default_spec.rb +21 -0
  248. data/spec/public/router/deferred_spec.rb +22 -0
  249. data/spec/public/router/fixation_spec.rb +27 -0
  250. data/spec/public/router/fixture/log/merb_test.log +1556 -0
  251. data/spec/public/router/namespace_spec.rb +113 -0
  252. data/spec/public/router/nested_matches_spec.rb +97 -0
  253. data/spec/public/router/nested_resources_spec.rb +41 -0
  254. data/spec/public/router/resource_spec.rb +37 -0
  255. data/spec/public/router/resources_spec.rb +82 -0
  256. data/spec/public/router/spec_helper.rb +90 -0
  257. data/spec/public/router/special_spec.rb +61 -0
  258. data/spec/public/router/string_spec.rb +61 -0
  259. data/spec/public/template/template_spec.rb +104 -0
  260. data/spec/public/template/templates/error.html.erb +2 -0
  261. data/spec/public/template/templates/template.html.erb +1 -0
  262. data/spec/public/template/templates/template.html.myt +1 -0
  263. data/spec/public/test/controller_matchers_spec.rb +402 -0
  264. data/spec/public/test/controllers/controller_assertion_mock.rb +7 -0
  265. data/spec/public/test/controllers/dispatch_controller.rb +11 -0
  266. data/spec/public/test/controllers/spec_helper_controller.rb +38 -0
  267. data/spec/public/test/multipart_request_helper_spec.rb +159 -0
  268. data/spec/public/test/multipart_upload_text_file.txt +1 -0
  269. data/spec/public/test/request_helper_spec.rb +221 -0
  270. data/spec/public/test/route_helper_spec.rb +71 -0
  271. data/spec/public/test/route_matchers_spec.rb +162 -0
  272. data/spec/public/test/view_helper_spec.rb +96 -0
  273. data/spec/public/test/view_matchers_spec.rb +183 -0
  274. data/spec/spec_helper.rb +68 -0
  275. metadata +493 -41
  276. data/README.txt +0 -3
  277. data/lib/extlib.rb +0 -32
  278. data/lib/extlib/assertions.rb +0 -8
  279. data/lib/extlib/blank.rb +0 -42
  280. data/lib/extlib/class.rb +0 -175
  281. data/lib/extlib/hash.rb +0 -410
  282. data/lib/extlib/hook.rb +0 -366
  283. data/lib/extlib/inflection.rb +0 -141
  284. data/lib/extlib/lazy_array.rb +0 -106
  285. data/lib/extlib/mash.rb +0 -143
  286. data/lib/extlib/module.rb +0 -37
  287. data/lib/extlib/object.rb +0 -165
  288. data/lib/extlib/object_space.rb +0 -13
  289. data/lib/extlib/pathname.rb +0 -5
  290. data/lib/extlib/pooling.rb +0 -233
  291. data/lib/extlib/rubygems.rb +0 -38
  292. data/lib/extlib/simple_set.rb +0 -39
  293. data/lib/extlib/string.rb +0 -132
  294. data/lib/extlib/struct.rb +0 -8
  295. data/lib/extlib/tasks/release.rb +0 -9
  296. data/lib/extlib/time.rb +0 -12
  297. data/lib/extlib/version.rb +0 -3
  298. data/lib/extlib/virtual_file.rb +0 -10
@@ -0,0 +1,91 @@
1
+ module Merb
2
+
3
+ # Cookies are read and written through Merb::Controller#cookies. The cookies
4
+ # you read are those received in request along with those that have been set
5
+ # during the current request. The cookies you write will be sent out with the
6
+ # response. Cookies are read by value (so you won't get the cookie object
7
+ # itself back -- just the value it holds).
8
+ class Cookies
9
+
10
+ # ==== Parameters
11
+ # request_cookies<Hash>:: Initial cookie store.
12
+ # headers<Hash>:: The response headers.
13
+ def initialize(request_cookies, headers)
14
+ @_cookies = request_cookies
15
+ @_headers = headers
16
+ end
17
+
18
+ # ==== Parameters
19
+ # name<~to_s>:: Name of the cookie.
20
+ #
21
+ # ==== Returns
22
+ # String:: Value of the cookie.
23
+ def [](name)
24
+ @_cookies[name]
25
+ end
26
+
27
+ # ==== Parameters
28
+ # name<~to_s>:: Name of the cookie.
29
+ # options<Hash, ~to_s>:: Options for the cookie being set (see below).
30
+ #
31
+ # ==== Options (options)
32
+ # :value<~to_s>:: Value of the cookie
33
+ # :path<String>:: The path for which this cookie applies. Defaults to "/".
34
+ # :expires<Time>:: Cookie expiry date.
35
+ #
36
+ # ==== Alternatives
37
+ # If options is not a hash, it will be used as the cookie value directly.
38
+ #
39
+ # ==== Examples
40
+ # cookies[:user] = "dave" # => Sets a simple session cookie
41
+ # cookies[:token] = { :value => user.token, :expires => Time.now + 2.weeks }
42
+ # # => Will set a cookie that expires in 2 weeks
43
+ def []=(name, options)
44
+ value = ''
45
+ if options.is_a?(Hash)
46
+ options = Mash.new(options)
47
+ value = options.delete(:value)
48
+ else
49
+ value = options
50
+ options = Mash.new
51
+ end
52
+ @_cookies[name] = value
53
+ set_cookie(name, Merb::Request.escape(value), options)
54
+ Merb.logger.info("Cookie set: #{name} => #{value} -- #{options.inspect}")
55
+ options
56
+ end
57
+
58
+ # Removes the cookie on the client machine by setting the value to an empty
59
+ # string and setting its expiration date into the past.
60
+ #
61
+ # ==== Parameters
62
+ # name<~to_s>:: Name of the cookie to delete.
63
+ # options<Hash>:: Additional options to pass to +set_cookie+.
64
+ def delete(name, options = {})
65
+ cookie = @_cookies.delete(name)
66
+ options = Mash.new(options)
67
+ options[:expires] = Time.at(0)
68
+ set_cookie(name, "", options)
69
+ Merb.logger.info("Cookie deleted: #{name} => #{cookie.inspect}")
70
+ cookie
71
+ end
72
+
73
+ # ==== Parameters
74
+ # name<~to_s>:: Name of the cookie.
75
+ # value<~to_s>:: Value of the cookie.
76
+ # options<Hash>:: Additional options for the cookie (see below).
77
+ #
78
+ # ==== Options (options)
79
+ # :path<String>:: The path for which this cookie applies. Defaults to "/".
80
+ # :expires<Time>:: Cookie expiry date.
81
+ def set_cookie(name, value, options)
82
+ options[:path] = '/' unless options[:path]
83
+ if expiry = options[:expires]
84
+ options[:expires] = expiry.gmtime.strftime(Merb::Const::COOKIE_EXPIRATION_FORMAT)
85
+ end
86
+ # options are sorted for testing purposes
87
+ (@_headers['Set-Cookie'] ||=[]) << "#{name}=#{value}; " +
88
+ options.map{|k, v| "#{k}=#{v};"}.sort.join(' ')
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,278 @@
1
+ class Merb::Dispatcher
2
+ DEFAULT_ERROR_TEMPLATE = File.expand_path(File.dirname(__FILE__) / 'exceptions.html')
3
+
4
+ class << self
5
+
6
+ attr_accessor :use_mutex
7
+
8
+ @@mutex = Mutex.new
9
+ @@work_queue = Queue.new
10
+
11
+ def work_queue
12
+ @@work_queue
13
+ end
14
+
15
+ Merb::Dispatcher.use_mutex = ::Merb::Config[:use_mutex]
16
+
17
+ # This is where we grab the incoming request REQUEST_URI and use that in
18
+ # the merb RouteMatcher to determine which controller and method to run.
19
+ # Returns a 2 element tuple of: [controller, action]
20
+ #
21
+ # ControllerExceptions are rescued here and redispatched.
22
+ #
23
+ # ==== Parameters
24
+ # rack_env<Rack::Environment>::
25
+ # The rack environment, which is used to instantiate a Merb::Request
26
+ # response<IO>::
27
+ # An IO object to hold the response
28
+ #
29
+ # ==== Returns
30
+ # Array[Merb::Controller, Symbol]::
31
+ # An array containing the Merb::Controller and the action that was
32
+ # dispatched to.
33
+ def handle(rack_env)
34
+ start = Time.now
35
+ request = Merb::Request.new(rack_env)
36
+ Merb.logger.info "Started request handling: #{start.to_s}"
37
+
38
+ route_index, route_params = Merb::Router.match(request)
39
+ route = Merb::Router.routes[route_index] if route_index
40
+
41
+ return dispatch_redirection(request,route) if route && route.behavior.redirects?
42
+
43
+ if route_params.empty?
44
+ raise ::Merb::ControllerExceptions::NotFound, "No routes match the request: #{request.uri}."
45
+ end
46
+ request.route_params = route_params
47
+ request.params.merge! route_params
48
+
49
+ controller_name = (route_params[:namespace] ? route_params[:namespace] + '/' : '') + route_params[:controller]
50
+
51
+ unless controller_name
52
+ raise Merb::ControllerExceptions::NotFound, "Route matched, but route did not specify a controller. Did you forgot to add :controller => \"people\" or :controller segment to route definition? Here is what's specified: #{request.route_params.inspect}"
53
+ end
54
+
55
+ Merb.logger.debug("Routed to: #{request.route_params.inspect}")
56
+
57
+ cnt = controller_name.snake_case.to_const_string
58
+
59
+ if !Merb::Controller._subclasses.include?(cnt)
60
+ raise Merb::ControllerExceptions::NotFound, "Controller '#{cnt}' not found. If Merb tries to look for a controller for static files, you way need to check up your Rackup file, see Problems section at: http://wiki.merbivore.com/pages/rack-middleware"
61
+ end
62
+ if cnt == "Application"
63
+ raise Merb::ControllerExceptions::NotFound, "The 'Application' controller has no public actions"
64
+ end
65
+
66
+ begin
67
+ klass = Object.full_const_get(cnt)
68
+ rescue NameError => e
69
+ Merb.logger.warn!("Controller class not found for controller #{controller_name}: #{e.message}")
70
+ raise Merb::ControllerExceptions::NotFound
71
+ end
72
+
73
+ Merb.logger.info("Params: #{klass._filter_params(request.params).inspect}")
74
+
75
+ action = route_params[:action]
76
+
77
+ if route.allow_fixation? && request.params.key?(Merb::Controller._session_id_key)
78
+ Merb.logger.info("Fixated session id: #{Merb::Controller._session_id_key}")
79
+ request.cookies[Merb::Controller._session_id_key] = request.params[Merb::Controller._session_id_key]
80
+ end
81
+
82
+ controller = dispatch_action(klass, action, request)
83
+ controller._benchmarks[:dispatch_time] = Time.now - start
84
+ controller.route = route
85
+ Merb.logger.info controller._benchmarks.inspect
86
+ Merb.logger.flush
87
+
88
+ controller
89
+ # this is the custom dispatch_exception; it allows failures to still be dispatched
90
+ # to the error controller
91
+ rescue => exception
92
+ Merb.logger.error(Merb.exception(exception))
93
+ unless request.xhr?
94
+ exception = controller_exception(exception)
95
+ dispatch_exception(request, exception)
96
+ else
97
+ Struct.new(:headers, :status, :body).new({}, 500,
98
+ <<-HERE
99
+ #{exception.message}
100
+
101
+ Params:
102
+ #{(request.params || {}).map { |p,v| " #{p}: #{v}\n"}.join("\n")}
103
+
104
+ Session:
105
+ #{(request.session || {}).map { |p,v| " #{p}: #{v}\n"}.join("\n")}
106
+
107
+ Cookies:
108
+ #{(request.cookies || {}).map { |p,v| " #{p}: #{v}\n"}.join("\n")}
109
+
110
+ Stacktrace:
111
+ #{exception.backtrace.join("\n")}
112
+ HERE
113
+ )
114
+ end
115
+ end
116
+
117
+ private
118
+ # Setup the controller and call the chosen action
119
+ #
120
+ # ==== Parameters
121
+ # klass<Merb::Controller>:: The controller class to dispatch to.
122
+ # action<Symbol>:: The action to dispatch.
123
+ # request<Merb::Request>::
124
+ # The Merb::Request object that was created in #handle
125
+ # response<IO>:: The response object passed in from Mongrel
126
+ # status<Integer>:: The status code to respond with.
127
+ #
128
+ # ==== Returns
129
+ # Array[Merb::Controller, Symbol]::
130
+ # An array containing the Merb::Controller and the action that was
131
+ # dispatched to.
132
+ def dispatch_action(klass, action, request, status=200)
133
+ # build controller
134
+ controller = klass.new(request, status)
135
+ if use_mutex
136
+ @@mutex.synchronize { controller._dispatch(action) }
137
+ else
138
+ controller._dispatch(action)
139
+ end
140
+ controller
141
+ end
142
+
143
+ # Re-route the current request to the Exception controller if it is
144
+ # available, and try to render the exception nicely.
145
+ #
146
+ # You can handle exceptions by implementing actions for specific
147
+ # exceptions such as not_found or for entire classes of exceptions
148
+ # such as client_error
149
+ #
150
+ # If it is not available then just render a simple text error.
151
+ #
152
+ # ==== Parameters
153
+ # request<Merb::Request>::
154
+ # The request object associated with the failed request.
155
+ # response<IO>::
156
+ # The response object to put the response into.
157
+ # exception<Object>::
158
+ # The exception object that was created when trying to dispatch the
159
+ # original controller.
160
+ #
161
+ # ==== Returns
162
+ # Array[Merb::Controller, String]::
163
+ # An array containing the Merb::Controller and the name of the exception
164
+ # that triggrered #dispatch_exception. For instance, a NotFound exception
165
+ # will be "not_found".
166
+ def dispatch_exception(request, exception)
167
+ exception_klass = exception.class
168
+ begin
169
+ klass = ::Exceptions rescue Merb::Controller
170
+ request.params[:original_params] = request.params.dup rescue {}
171
+ request.params[:original_session] = request.session.dup rescue {}
172
+ request.params[:original_cookies] = request.cookies.dup rescue {}
173
+ request.params[:exception] = exception
174
+ request.params[:action] = exception_klass.name
175
+
176
+ dispatch_action(klass, exception_klass.name, request, exception.class.status)
177
+ rescue => dispatch_issue
178
+ dispatch_issue = controller_exception(dispatch_issue)
179
+ # when no action/template exist for an exception, or an
180
+ # exception occurs on an InternalServerError the message is
181
+ # rendered as simple text.
182
+
183
+ # ControllerExceptions raised from exception actions are
184
+ # dispatched back into the Exceptions controller
185
+ if dispatch_issue.is_a?(Merb::ControllerExceptions::NotFound)
186
+ # If a handler for a specific exception is not found, keep retrying
187
+ # with the more general cases until we reach the base exception.
188
+ unless exception_klass == Merb::ControllerExceptions::Base
189
+ exception_klass = exception_klass.superclass
190
+ retry
191
+ else
192
+ dispatch_default_exception(klass, request, exception)
193
+ end
194
+ elsif request.params[:exception].is_a?(dispatch_issue.class)
195
+ dispatch_default_exception(klass, request, dispatch_issue)
196
+ elsif dispatch_issue.is_a?(Merb::ControllerExceptions::InternalServerError)
197
+ dispatch_default_exception(klass, request, dispatch_issue)
198
+ else
199
+ exception = dispatch_issue
200
+ retry
201
+ end
202
+ end
203
+ end
204
+
205
+ # If no custom actions are available to render an exception then the errors
206
+ # will end up here for processing
207
+ #
208
+ # ==== Parameters
209
+ # klass<Merb::Controller>::
210
+ # The class of the controller to use for exception dispatch.
211
+ # request<Merb::Request>::
212
+ # The Merb request that produced the original error.
213
+ # response<IO>::
214
+ # The response object that the response will be put into.
215
+ # e<Exception>::
216
+ # The exception that caused #dispatch_exception to be called.
217
+ #
218
+ # ==== Returns
219
+ # Array[Merb::Controller, String]::
220
+ # An array containing the Merb::Controller that was dispatched to and the
221
+ # error's name. For instance, a NotFound error's name is "not_found".
222
+ def dispatch_default_exception(klass, request, e)
223
+ controller = klass.new(request, e.class.status)
224
+ if e.is_a? Merb::ControllerExceptions::Redirection
225
+ controller.headers.merge!('Location' => e.message)
226
+ controller.body = %{ } #fix
227
+ else
228
+ controller.instance_variable_set("@exception", e) # for ERB
229
+ controller.instance_variable_set("@exception_name", e.name.split("_").map {|x| x.capitalize}.join(" "))
230
+ controller.body = controller.send(Merb::Template.template_for(DEFAULT_ERROR_TEMPLATE))
231
+ end
232
+ controller
233
+ end
234
+
235
+ # Set up a faux controller to do redirection from the router
236
+ #
237
+ # ==== Parameters
238
+ # request<Merb::Request>::
239
+ # The Merb::Request object that was created in #handle
240
+ # route<Merb::Router::Route>:: Matched route object
241
+ #
242
+ # ==== Example
243
+ # r.match("/my/old/crusty/url").redirect("http://example.com/index.html")
244
+ #
245
+ # ==== Returns
246
+ # Merb::Controller::
247
+ # Merb::Controller set with redirect headers and a 301/302 status
248
+ def dispatch_redirection(request, route)
249
+ status = route.behavior.redirect_status
250
+ url = route.behavior.redirect_url
251
+
252
+ controller = Merb::Controller.new(request,status)
253
+
254
+ Merb.logger.info("Dispatcher redirecting to: #{url} (#{status})")
255
+
256
+ controller.headers['Location'] = url
257
+ controller.body = "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>"
258
+ controller
259
+ end
260
+
261
+
262
+ # Wraps any non-ControllerException errors in an InternalServerError ready
263
+ # for displaying over HTTP.
264
+ #
265
+ # ==== Parameters
266
+ # e<Exception>::
267
+ # The exception that caused #dispatch_exception to be called.
268
+ #
269
+ # ==== Returns
270
+ # Merb::InternalServerError::
271
+ # An internal server error wrapper for the exception.
272
+ def controller_exception(e)
273
+ e.kind_of?(Merb::ControllerExceptions::Base) ?
274
+ e : Merb::ControllerExceptions::InternalServerError.new(e)
275
+ end
276
+
277
+ end
278
+ end
@@ -0,0 +1,303 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
4
+ <title><%= @exception_name %></title>
5
+ <style type="text/css" media="screen">
6
+ body {
7
+ font-family:arial;
8
+ font-size:11px;
9
+ }
10
+ h1 {
11
+ font-size:48px;
12
+ letter-spacing:-4px;
13
+ margin:0;
14
+ line-height:36px;
15
+ color:#333;
16
+ }
17
+ h1 sup {
18
+ font-size: 0.5em;
19
+ }
20
+ h1 sup.error_500, h1 sup.error_400 {
21
+ color:#990E05;
22
+ }
23
+ h1 sup.error_100, h1 sup.error_200 {
24
+ color:#00BF10;
25
+ }
26
+ h1 sup.error_300 {
27
+ /* pretty sure you cant 'see' status 300
28
+ errors but if you could I think they
29
+ would be blue */
30
+ color:#1B2099;
31
+ }
32
+ h2 {
33
+ font-size:36px;
34
+ letter-spacing:-3px;
35
+ margin:0;
36
+ line-height:28px;
37
+ color:#444;
38
+ }
39
+ h3 {
40
+ cursor: pointer;
41
+ color: #006;
42
+ text-decoration: underline;
43
+ }
44
+ a, a:visited {
45
+ color:#00BF10;
46
+ }
47
+ .internalError {
48
+ width:800px;
49
+ margin:50px auto;
50
+ }
51
+ .header {
52
+ border-bottom:10px solid #333;
53
+ margin-bottom:1px;
54
+ background-image: url("data:image/gif;base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7");
55
+ padding:20px;
56
+ }
57
+ table.listing {
58
+ border-collapse: collapse;
59
+ font-size: 12px;
60
+ width: 100%;
61
+ }
62
+
63
+ table.listing th {
64
+ background-color: #000;
65
+ color: #fff;
66
+ }
67
+
68
+ table.listing td, table.listing th {
69
+ padding: 5px;
70
+ text-align: left;
71
+ vertical-align: top;
72
+ }
73
+
74
+ table.listing tr.odd {
75
+ background-color: #ccc;
76
+ }
77
+
78
+ table.listing tr.even {
79
+ background-color: #aaa;
80
+ }
81
+
82
+ table.listing td[colspan=2] {
83
+ text-align: center;
84
+ }
85
+
86
+ table.trace {
87
+ width:100%;
88
+ font-family:courier, monospace;
89
+ letter-spacing:-1px;
90
+ border-collapse: collapse;
91
+ border-spacing:0;
92
+ }
93
+ table.trace tr td{
94
+ padding:0;
95
+ height:26px;
96
+ font-size:13px;
97
+ vertical-align:middle;
98
+ }
99
+ table.trace tr.file{
100
+ border-top:2px solid #fff;
101
+ background-color:#F3F3F3;
102
+ }
103
+ table.trace tr.source {
104
+ background-color:#F8F8F8;
105
+ display:none;
106
+ }
107
+ table.trace .open tr.source {
108
+ display:table-row;
109
+ }
110
+ table.trace tr.file td.expand {
111
+ width:23px;
112
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAIAAABvSEP3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUeNqMVL+TwUAYxaRIOlEhlZHGDAUzzOQ61+AqXMV1lJSU7q/QRqm8KFUcJTNn5qJkaPyoKKVz7y4mF8na5Kt29tt9+/Z97/u81+vVQ4r9frdarS6Xi7ETDIZisRjxMGPfmk4niNPpZE+xLAugbPaZ53nzvtfMBe/3+/3dbuehBrAKhZdUKkVAWa9Xsiybv0CPZDJZLr/qa5/BwgwRjYqOKIvFYjQa/aNommZh0Ww2K5UqzwfoQOPxaLPZ3FAmk0+7lplMpt1u53J5OpBOR0eZEE9wHJfP5zud93g88QhluwWbjW+5VOmKBgKBer3eaDTDYeGBQF8+x7rqIYoiPgixWJazpA6HA+MSxRArkUgMh0M409g8Ho8+9wYxxCqVSq1W26EDHGM2m4HOHQrEc38f/Yn7cLmlIRhBENzcx8cVRZnPZ/YUep2BWkjTIfA+PKVpZAXR5QxsjiqCKvGEqqp443w+0dvy17swqD0HB3S73V5PpkNg1qBqt8kwGCjmPkinM0QJbIoEa7U6UG6ToVgs4V9G2g0ESoP5Aoi7KYX5oCgf8IKbkvn9/mr1LRQKESamzgJy0g0tSZIuB3nuGqRU9Vv9C4sKkUhEkp4soxvxI8AAhWrrtXa3X8EAAAAASUVORK5CYII=);
113
+ background-position:top left;
114
+ background-repeat:no-repeat;
115
+ }
116
+ table.trace tr.file td.expand div {
117
+ width:23px;
118
+ }
119
+ table.trace .open tr.file td.expand {
120
+ width:19px;
121
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNrslK1ywkAUhcMOBomEOiSdqLxEBJX0NaijOsjyHGGmCGyQQYaiiiw4gktkcOmZbpsuuzQ/M5XnqJ2d3S/n3nM3rTzPLUP7/Tt0+pLcGQwG3W53OLyHzPMtjYL7q9UqSRLrD4E1Gj1orCvKYuFHUWTVkOM44/HjDcp8/lL4r6NerzeZPMm1KFw0QkDn83m5fP2lHA4fNQvRtNvtjsfDd0WzmSfb2e/fdTqdOvdh/HLJZLOn0+d2HJ+KRGzbdl23EpFlmed5cp2maRzHQq1lvQ5KMi6EUZBGfup6E1pTfd+vrGW7jbQ2C9hTt9BpqNyIWaAwAy6xg2eBz5iRC/NomiZhGN5sqmnkauo0BUGgVQoBjQ80oCACgNQdZHfTYBkF2mxCtWWAqunWpahxIDUt3QYUxIFQpJHyIWpXjinabKbbwItMHT+NyjchrP8QKaSQQgoppJBCCimkkEIKKaSQQgoppJBCCimkkEIKKaSo+hRgAEFD17X08O2NAAAAAElFTkSuQmCC);
122
+ background-position:top left;
123
+ background-repeat:no-repeat;
124
+ }
125
+ table.trace .open tr.file td.expand div {
126
+ width:19px;
127
+ }
128
+ table.trace tr.source td.collapse {
129
+ width:19px;
130
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAVxJREFUeNrs0zFygkAUBmBlUkgJHdABlQwVkVJKKUxBYWbkALTxMJwhltyDFkss03IF8pudIcwaDaDl/6pd2P327b7d+eHwMXs4lNkzggoVKlSoUKFChQoVKlSoUKFChQoVKlSoUKFChQqVEYqm6ft9+qiSJEkYho7jTlcw2fd9NOI4nq4gEdFwXXe1Cqco63VkWVbXRTqLhTpOwQRpF7quR1E0TgGhqvLKUFCyoQqG/rks3O6kZKW/eRFpevOCoGTXVTcMQ5EyxyDEkML1c5RzuZOICIyXqn7JBVez6282MWrx731HOv2qB8Hri2lamNk0DfpVVdV1Peodappmmua8bdvzuc7zfNprzrLMth1FnGh/X8MjCAIQv/cFz/+65PcDh7rbvYv2ZUfdj+PxsyzLgVl0hKwgTqeqKApx2LeOc7t98zyv/1FWOgvx9RPii23bmL9cetJ8Ed8CDAC6aFW8bCzFhwAAAABJRU5ErkJggg==);
131
+ background-position:bottom left;
132
+ background-repeat:no-repeat;
133
+ background-color:#6F706F;
134
+ }
135
+ table.trace tr td.path {
136
+ padding-left:10px;
137
+ }
138
+ table.trace tr td.code {
139
+ padding-left:35px;
140
+ white-space: pre;
141
+ line-height:9px;
142
+ padding-bottom:10px;
143
+ }
144
+ table.trace tr td.code em {
145
+ font-weight:bold;
146
+ color:#00BF10;
147
+ }
148
+ table.trace tr td.code a {
149
+ width: 20px;
150
+ float: left;
151
+ }
152
+ table.trace tr td.code .more {
153
+ color:#666;
154
+ }
155
+ table.trace tr td.line {
156
+ width:30px;
157
+ text-align:right;
158
+ padding-right:4px;
159
+ }
160
+ .footer {
161
+ margin-top:5px;
162
+ font-size:11px;
163
+ color:#444;
164
+ text-align:right;
165
+ }
166
+ </style>
167
+ </head>
168
+ <body>
169
+ <div class="internalError">
170
+
171
+ <div class="header">
172
+ <h1><%= @exception_name %> <sup class="error_<%= @exception.class.status %>"><%= @exception.class.status %></sup></h1>
173
+ <% if show_details = ::Merb::Config[:exception_details] -%>
174
+ <h2><%= html_escape(@exception.message) %></h2>
175
+ <% else -%>
176
+ <h2>Sorry about that...</h2>
177
+ <% end -%>
178
+
179
+ <h3>Parameters</h3>
180
+ <table class="listing" style="display: none">
181
+ <thead>
182
+ <tr><th width="25%">Parameter</th><th width="75%">Value</th></tr>
183
+ </thead>
184
+ <tbody>
185
+ <% params[:original_params].each_with_index do |param_value, i| %>
186
+ <tr class="<%= i % 2 == 0 ? "even" : "odd" %>"><td><%= param_value.first %></td><td><%= param_value.last.inspect %></td></tr>
187
+ <% end %>
188
+ <%= "<tr class='odd'><td colspan='2'>None</td></tr>" if params[:original_params].empty? %>
189
+ </tbody>
190
+ </table>
191
+
192
+ <h3>Session</h3>
193
+ <table class="listing" style="display: none">
194
+ <thead>
195
+ <tr><th width="25%">Key</th><th width="75%">Value</th></tr>
196
+ </thead>
197
+ <tbody>
198
+ <% if params[:original_session].respond_to?( :data )%>
199
+ <% params[:original_session].data.each_with_index do |param_value, i| %>
200
+ <tr class="<%= i % 2 == 0 ? "even" : "odd" %>"><td><%= param_value.first %></td><td><%= param_value.last.inspect %></td></tr>
201
+ <% end %>
202
+ <% else %>
203
+ <% params[:original_session].each_with_index do |param_value, i| %>
204
+ <tr class="<%= i % 2 == 0 ? "even" : "odd" %>"><td><%= param_value.first %></td><td><%= param_value.last.inspect %></td></tr>
205
+ <% end %>
206
+ <%= "<tr class='odd'><td colspan='2'>None</td></tr>" if params[:original_session].empty? %>
207
+ <% end %>
208
+ </tbody>
209
+ </table>
210
+
211
+ <h3>Cookies</h3>
212
+ <table class="listing" style="display: none">
213
+ <thead>
214
+ <tr><th width="25%">Cookie</th><th width="75%">Value</th></tr>
215
+ </thead>
216
+ <tbody>
217
+ <% params[:original_cookies].each_with_index do |param_value, i| %>
218
+ <tr class="<%= i % 2 == 0 ? "even" : "odd" %>"><td><%= param_value.first %></td><td><%= param_value.last.inspect %></td></tr>
219
+ <% end %>
220
+ <%= "<tr class='odd'><td colspan='2'>None</td></tr>" if params[:original_cookies].empty? %>
221
+ </tbody>
222
+ </table>
223
+
224
+ <h3>Named Routes</h3>
225
+ <table class="listing" style="display: none">
226
+ <% unless Merb::Router.named_routes.empty? %>
227
+ <thead>
228
+ <tr><th width="25%">Name</th><th width="75%">Route</th></tr>
229
+ </thead>
230
+ <tbody>
231
+ <% Merb::Router.named_routes.each_with_index do |name_route, i| %>
232
+ <tr class="<%= i % 2 == 0 ? "even" : "odd" %>"><td><%= name_route.first %></td><td><%= name_route.last %></td></tr>
233
+ <% end %>
234
+ </tbody>
235
+ <% else %>
236
+ <tr><td colspan="2">None</td></tr>
237
+ <% end %>
238
+ </table>
239
+ </div>
240
+
241
+ <% if show_details %>
242
+ <table class="trace">
243
+ <% @exception.backtrace.each_with_index do |line, index| %>
244
+ <tbody class="close">
245
+ <tr class="file">
246
+ <td class="expand"><div>&nbsp;</div></td>
247
+ <td class="path">
248
+ <%= (line.match(/^([^:]+)/)[1] rescue 'unknown').sub(/\/((opt|usr)\/local\/lib\/(ruby\/)?(gems\/)?(1.8\/)?(gems\/)?|.+\/app\/)/, '') %>
249
+ <% unless line.match(/\.erb:/) %>
250
+ in "<strong><%= line.match(/:in `(.+)'$/)[1] rescue '?' %></strong>"
251
+ <% else %>
252
+ (<strong>ERB Template</strong>)
253
+ <% end %>
254
+ </td>
255
+ <td class="line">
256
+ <a href="txmt://open?url=file://<%=file = (line.match(/^([^:]+)/)[1] rescue 'unknown')%>&amp;line=<%= lineno = line.match(/:([0-9]+):/)[1] rescue '?' %>"><%=lineno%></a>&nbsp;
257
+ </td>
258
+ </tr>
259
+ <tr class="source">
260
+ <td class="collapse">
261
+ </td>
262
+ <td class="code" colspan="2"><% (__caller_lines__(file, lineno, 5) rescue []).each do |llineno, lcode, lcurrent| %>
263
+ <a href="txmt://open?url=file://<%=file%>&amp;line=<%=llineno%>"><%= llineno %></a><%='<em>' if llineno==lineno.to_i %><%= lcode.size > 90 ? Erubis::XmlHelper.escape_xml(lcode[0..90])+'<span class="more">......</span>' : Erubis::XmlHelper.escape_xml(lcode) %><%='</em>' if llineno==lineno.to_i %>
264
+ <% end %>
265
+
266
+ </td>
267
+ </tr>
268
+ </tbody>
269
+ <% end %>
270
+ </table>
271
+ <script type="text/javascript" charset="utf-8">
272
+ els = document.getElementsByTagName('td');
273
+ for(i=0; i<els.length; i++){
274
+ // swap the open & closed classes
275
+ if(els[i].className=='expand' || els[i].className=='collapse'){
276
+ els[i].onclick = function(e){
277
+ tbody = this.parentNode.parentNode;
278
+ if(tbody.className=='open'){
279
+ tbody.className='closed';
280
+ }else{
281
+ tbody.className='open';
282
+ }
283
+ }
284
+ }
285
+ }
286
+ els = document.getElementsByTagName("h3");
287
+ for(i=0; i<els.length; i++) {
288
+ els[i].onclick = function(e) {
289
+ var tag = this.nextSibling;
290
+ while(tag.nodeType != 1) {
291
+ tag = tag.nextSibling;
292
+ }
293
+ tag.style.display = tag.style.display == "none" ? "" : "none";
294
+ }
295
+ }
296
+ </script>
297
+ <% end %>
298
+ <div class="footer">
299
+ lots of love, from <a href="#">merb</a>
300
+ </div>
301
+ </div>
302
+ </body>
303
+ </html>