thorero 0.9.4.4 → 0.9.4.5

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 (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>