merb-core 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. data/CHANGELOG +136 -2
  2. data/CONTRIBUTORS +6 -0
  3. data/PUBLIC_CHANGELOG +38 -0
  4. data/Rakefile +38 -30
  5. data/lib/merb-core.rb +88 -23
  6. data/lib/merb-core/bootloader.rb +235 -51
  7. data/lib/merb-core/config.rb +121 -36
  8. data/lib/merb-core/controller/abstract_controller.rb +59 -36
  9. data/lib/merb-core/controller/exceptions.rb +2 -15
  10. data/lib/merb-core/controller/merb_controller.rb +44 -1
  11. data/lib/merb-core/controller/mime.rb +4 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +38 -21
  13. data/lib/merb-core/controller/mixins/render.rb +44 -29
  14. data/lib/merb-core/controller/mixins/responder.rb +3 -31
  15. data/lib/merb-core/controller/template.rb +45 -21
  16. data/lib/merb-core/core_ext/kernel.rb +60 -32
  17. data/lib/merb-core/dispatch/default_exception/default_exception.rb +2 -2
  18. data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +3 -1
  19. data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +71 -67
  20. data/lib/merb-core/dispatch/default_exception/views/index.html.erb +7 -3
  21. data/lib/merb-core/dispatch/dispatcher.rb +3 -3
  22. data/lib/merb-core/dispatch/request.rb +56 -9
  23. data/lib/merb-core/dispatch/router.rb +159 -133
  24. data/lib/merb-core/dispatch/router/behavior.rb +462 -703
  25. data/lib/merb-core/dispatch/router/cached_proc.rb +3 -3
  26. data/lib/merb-core/dispatch/router/resources.rb +289 -0
  27. data/lib/merb-core/dispatch/router/route.rb +514 -294
  28. data/lib/merb-core/dispatch/session.rb +4 -2
  29. data/lib/merb-core/logger.rb +213 -202
  30. data/lib/merb-core/plugins.rb +9 -1
  31. data/lib/merb-core/rack.rb +3 -1
  32. data/lib/merb-core/rack/adapter.rb +7 -4
  33. data/lib/merb-core/rack/adapter/abstract.rb +188 -0
  34. data/lib/merb-core/rack/adapter/ebb.rb +12 -13
  35. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -15
  36. data/lib/merb-core/rack/adapter/irb.rb +3 -2
  37. data/lib/merb-core/rack/adapter/mongrel.rb +22 -15
  38. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +4 -16
  39. data/lib/merb-core/rack/adapter/thin.rb +21 -22
  40. data/lib/merb-core/rack/adapter/thin_turbo.rb +4 -11
  41. data/lib/merb-core/rack/adapter/webrick.rb +54 -18
  42. data/lib/merb-core/rack/application.rb +4 -4
  43. data/lib/merb-core/rack/handler/mongrel.rb +12 -13
  44. data/lib/merb-core/rack/middleware/csrf.rb +1 -1
  45. data/lib/merb-core/rack/stream_wrapper.rb +41 -0
  46. data/lib/merb-core/server.rb +157 -90
  47. data/lib/merb-core/tasks/gem_management.rb +267 -0
  48. data/lib/merb-core/tasks/merb.rb +1 -0
  49. data/lib/merb-core/tasks/merb_rake_helper.rb +48 -34
  50. data/lib/merb-core/tasks/stats.rake +1 -1
  51. data/lib/merb-core/test.rb +9 -3
  52. data/lib/merb-core/test/helpers.rb +1 -0
  53. data/lib/merb-core/test/helpers/mock_request_helper.rb +393 -0
  54. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -2
  55. data/lib/merb-core/test/helpers/request_helper.rb +40 -372
  56. data/lib/merb-core/test/helpers/route_helper.rb +16 -2
  57. data/lib/merb-core/test/matchers.rb +1 -0
  58. data/lib/merb-core/test/matchers/controller_matchers.rb +4 -247
  59. data/lib/merb-core/test/matchers/request_matchers.rb +140 -0
  60. data/lib/merb-core/test/matchers/view_matchers.rb +22 -4
  61. data/lib/merb-core/test/run_specs.rb +118 -26
  62. data/lib/merb-core/test/test_ext/rspec.rb +181 -0
  63. data/lib/merb-core/version.rb +1 -9
  64. metadata +10 -342
  65. data/docs/bootloading.dox +0 -58
  66. data/docs/documentation_standards +0 -40
  67. data/docs/merb-core-call-stack-diagram.mmap +0 -0
  68. data/docs/merb-core-call-stack-diagram.pdf +0 -0
  69. data/docs/merb-core-call-stack-diagram.png +0 -0
  70. data/docs/new_render_api +0 -51
  71. data/lib/merb-core/vendor/facets.rb +0 -2
  72. data/lib/merb-core/vendor/facets/dictionary.rb +0 -433
  73. data/lib/merb-core/vendor/facets/inflect.rb +0 -342
  74. data/spec/private/config/adapter_spec.rb +0 -32
  75. data/spec/private/config/config_spec.rb +0 -202
  76. data/spec/private/config/environment_spec.rb +0 -13
  77. data/spec/private/config/merb_spec.rb +0 -34
  78. data/spec/private/config/spec_helper.rb +0 -1
  79. data/spec/private/core_ext/kernel_spec.rb +0 -159
  80. data/spec/private/dispatch/bootloader_spec.rb +0 -24
  81. data/spec/private/dispatch/fixture/app/controllers/application.rb +0 -4
  82. data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +0 -25
  83. data/spec/private/dispatch/fixture/app/controllers/foo.rb +0 -19
  84. data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +0 -8
  85. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +0 -37
  86. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +0 -216
  87. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +0 -38
  88. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +0 -40
  89. data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
  90. data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +0 -11
  91. data/spec/private/dispatch/fixture/config/black_hole.rb +0 -12
  92. data/spec/private/dispatch/fixture/config/environments/development.rb +0 -6
  93. data/spec/private/dispatch/fixture/config/environments/production.rb +0 -5
  94. data/spec/private/dispatch/fixture/config/environments/test.rb +0 -6
  95. data/spec/private/dispatch/fixture/config/init.rb +0 -45
  96. data/spec/private/dispatch/fixture/config/rack.rb +0 -11
  97. data/spec/private/dispatch/fixture/config/router.rb +0 -35
  98. data/spec/private/dispatch/fixture/log/merb_test.log +0 -8839
  99. data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
  100. data/spec/private/dispatch/fixture/public/merb.fcgi +0 -4
  101. data/spec/private/dispatch/fixture/public/stylesheets/master.css +0 -119
  102. data/spec/private/dispatch/route_params_spec.rb +0 -23
  103. data/spec/private/dispatch/spec_helper.rb +0 -1
  104. data/spec/private/router/behavior_spec.rb +0 -60
  105. data/spec/private/router/fixture/log/merb_test.log +0 -35
  106. data/spec/private/router/route_spec.rb +0 -418
  107. data/spec/private/router/router_spec.rb +0 -183
  108. data/spec/private/vendor/facets/plural_spec.rb +0 -564
  109. data/spec/private/vendor/facets/singular_spec.rb +0 -489
  110. data/spec/public/DEFINITIONS +0 -11
  111. data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +0 -1
  112. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +0 -1
  113. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +0 -1
  114. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +0 -1
  115. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +0 -1
  116. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +0 -1
  117. data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +0 -1
  118. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +0 -1
  119. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +0 -1
  120. data/spec/public/abstract_controller/controllers/cousins.rb +0 -41
  121. data/spec/public/abstract_controller/controllers/display.rb +0 -60
  122. data/spec/public/abstract_controller/controllers/filters.rb +0 -260
  123. data/spec/public/abstract_controller/controllers/helpers.rb +0 -41
  124. data/spec/public/abstract_controller/controllers/partial.rb +0 -121
  125. data/spec/public/abstract_controller/controllers/render.rb +0 -113
  126. data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +0 -1
  127. data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +0 -1
  128. data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +0 -1
  129. data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +0 -1
  130. data/spec/public/abstract_controller/controllers/views/layout/alt.erb +0 -1
  131. data/spec/public/abstract_controller/controllers/views/layout/custom.erb +0 -1
  132. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +0 -1
  133. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +0 -1
  134. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +0 -1
  135. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
  136. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +0 -1
  137. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +0 -1
  138. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +0 -1
  139. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +0 -1
  140. data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +0 -1
  141. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +0 -1
  142. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +0 -1
  143. data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +0 -1
  144. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +0 -1
  145. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +0 -1
  146. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +0 -1
  147. data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +0 -1
  148. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +0 -1
  149. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +0 -1
  150. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +0 -1
  151. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +0 -1
  152. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +0 -1
  153. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +0 -1
  154. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +0 -1
  155. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +0 -1
  156. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +0 -1
  157. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +0 -1
  158. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +0 -1
  159. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +0 -1
  160. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +0 -1
  161. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +0 -1
  162. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +0 -1
  163. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +0 -1
  164. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +0 -1
  165. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +0 -1
  166. data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +0 -1
  167. data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +0 -1
  168. data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +0 -1
  169. data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
  170. data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +0 -1
  171. data/spec/public/abstract_controller/display_spec.rb +0 -37
  172. data/spec/public/abstract_controller/filter_spec.rb +0 -136
  173. data/spec/public/abstract_controller/helper_spec.rb +0 -21
  174. data/spec/public/abstract_controller/partial_spec.rb +0 -61
  175. data/spec/public/abstract_controller/render_spec.rb +0 -90
  176. data/spec/public/abstract_controller/spec_helper.rb +0 -31
  177. data/spec/public/boot_loader/boot_loader_spec.rb +0 -33
  178. data/spec/public/boot_loader/spec_helper.rb +0 -1
  179. data/spec/public/controller/authentication_spec.rb +0 -174
  180. data/spec/public/controller/base_spec.rb +0 -88
  181. data/spec/public/controller/conditional_get_spec.rb +0 -100
  182. data/spec/public/controller/config/init.rb +0 -6
  183. data/spec/public/controller/controllers/authentication.rb +0 -74
  184. data/spec/public/controller/controllers/base.rb +0 -65
  185. data/spec/public/controller/controllers/conditional_get.rb +0 -35
  186. data/spec/public/controller/controllers/cookies.rb +0 -36
  187. data/spec/public/controller/controllers/dispatcher.rb +0 -35
  188. data/spec/public/controller/controllers/display.rb +0 -118
  189. data/spec/public/controller/controllers/redirect.rb +0 -36
  190. data/spec/public/controller/controllers/responder.rb +0 -93
  191. data/spec/public/controller/controllers/url.rb +0 -7
  192. data/spec/public/controller/controllers/views/layout/custom.html.erb +0 -1
  193. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +0 -1
  194. data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +0 -1
  195. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +0 -1
  196. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +0 -1
  197. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +0 -1
  198. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +0 -1
  199. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +0 -1
  200. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +0 -1
  201. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +0 -1
  202. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +0 -1
  203. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +0 -1
  204. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +0 -1
  205. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +0 -1
  206. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +0 -1
  207. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +0 -1
  208. data/spec/public/controller/cookies_spec.rb +0 -95
  209. data/spec/public/controller/dispatcher_spec.rb +0 -410
  210. data/spec/public/controller/display_spec.rb +0 -84
  211. data/spec/public/controller/redirect_spec.rb +0 -33
  212. data/spec/public/controller/responder_spec.rb +0 -169
  213. data/spec/public/controller/spec_helper.rb +0 -13
  214. data/spec/public/controller/url_spec.rb +0 -255
  215. data/spec/public/core/merb_core_spec.rb +0 -45
  216. data/spec/public/core_ext/fixtures/core_ext_dependency.rb +0 -2
  217. data/spec/public/core_ext/kernel_spec.rb +0 -88
  218. data/spec/public/core_ext/spec_helper.rb +0 -1
  219. data/spec/public/directory_structure/directory/app/controllers/application.rb +0 -3
  220. data/spec/public/directory_structure/directory/app/controllers/base.rb +0 -13
  221. data/spec/public/directory_structure/directory/app/controllers/custom.rb +0 -19
  222. data/spec/public/directory_structure/directory/app/views/base/template.html.erb +0 -1
  223. data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +0 -1
  224. data/spec/public/directory_structure/directory/config/router.rb +0 -3
  225. data/spec/public/directory_structure/directory/log/merb_test.log +0 -4588
  226. data/spec/public/directory_structure/directory_spec.rb +0 -43
  227. data/spec/public/logger/logger_spec.rb +0 -181
  228. data/spec/public/logger/spec_helper.rb +0 -1
  229. data/spec/public/rack/conditinal_get_middleware_spec.rb +0 -127
  230. data/spec/public/rack/csrf_middleware_spec.rb +0 -70
  231. data/spec/public/rack/rack_middleware_spec.rb +0 -99
  232. data/spec/public/rack/shared_example_groups.rb +0 -35
  233. data/spec/public/reloading/directory/app/controllers/application.rb +0 -3
  234. data/spec/public/reloading/directory/app/controllers/reload.rb +0 -6
  235. data/spec/public/reloading/directory/config/init.rb +0 -2
  236. data/spec/public/reloading/directory/log/merb_test.log +0 -288231
  237. data/spec/public/reloading/reload_spec.rb +0 -103
  238. data/spec/public/request/multipart_spec.rb +0 -41
  239. data/spec/public/request/request_spec.rb +0 -250
  240. data/spec/public/router/default_spec.rb +0 -21
  241. data/spec/public/router/deferred_spec.rb +0 -22
  242. data/spec/public/router/fixation_spec.rb +0 -49
  243. data/spec/public/router/fixture/log/merb_test.log +0 -524
  244. data/spec/public/router/namespace_spec.rb +0 -113
  245. data/spec/public/router/nested_matches_spec.rb +0 -97
  246. data/spec/public/router/nested_resources_spec.rb +0 -41
  247. data/spec/public/router/resource_spec.rb +0 -37
  248. data/spec/public/router/resources_spec.rb +0 -82
  249. data/spec/public/router/spec_helper.rb +0 -90
  250. data/spec/public/router/special_spec.rb +0 -61
  251. data/spec/public/router/string_spec.rb +0 -61
  252. data/spec/public/session/controllers/sessions.rb +0 -56
  253. data/spec/public/session/cookie_session_spec.rb +0 -73
  254. data/spec/public/session/memcached_session_spec.rb +0 -31
  255. data/spec/public/session/memory_session_spec.rb +0 -28
  256. data/spec/public/session/multiple_sessions_spec.rb +0 -74
  257. data/spec/public/session/no_session_spec.rb +0 -12
  258. data/spec/public/session/session_spec.rb +0 -106
  259. data/spec/public/template/template_spec.rb +0 -104
  260. data/spec/public/template/templates/error.html.erb +0 -2
  261. data/spec/public/template/templates/template.html.erb +0 -1
  262. data/spec/public/template/templates/template.html.myt +0 -1
  263. data/spec/public/test/controller_matchers_spec.rb +0 -412
  264. data/spec/public/test/controllers/controller_assertion_mock.rb +0 -7
  265. data/spec/public/test/controllers/dispatch_controller.rb +0 -11
  266. data/spec/public/test/controllers/spec_helper_controller.rb +0 -39
  267. data/spec/public/test/multipart_request_helper_spec.rb +0 -159
  268. data/spec/public/test/multipart_upload_text_file.txt +0 -1
  269. data/spec/public/test/request_helper_spec.rb +0 -269
  270. data/spec/public/test/route_helper_spec.rb +0 -78
  271. data/spec/public/test/route_matchers_spec.rb +0 -166
  272. data/spec/public/test/view_helper_spec.rb +0 -96
  273. data/spec/public/test/view_matchers_spec.rb +0 -183
  274. data/spec/spec_helper.rb +0 -121
@@ -1,6 +1,9 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+
1
4
  <html>
2
5
  <head>
3
- <meta http-equiv="Content-type" content="text/html; charset=utf-8">
6
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
4
7
  <title><%= humanize_exception(@exceptions.first) %></title>
5
8
  <%= partial :css %>
6
9
  </head>
@@ -14,7 +17,7 @@
14
17
  <% @exceptions.each_with_index do |exception,i| %>
15
18
  <li>
16
19
  <a href="#exception_<%= i %>"><%= humanize_exception(exception) %></a>
17
- <%= html_escape(exception.message.split("\n",2).first) %>
20
+ <%= escape_html(exception.message.split("\n",2).first) %>
18
21
  </li>
19
22
  <% end %>
20
23
  </ul>
@@ -51,7 +54,7 @@
51
54
  </h1>
52
55
  <%= error_codes(exception) %>
53
56
  <p class="options">
54
- <label class="all">All<input type="checkbox" autocomplete="off"></label>
57
+ <label class="all">All<input type="checkbox" autocomplete="off" /></label>
55
58
  <span class="all">
56
59
  <label class="app">App<input type="checkbox" checked="checked" autocomplete="off"/></label>
57
60
  <label class="framework">Framework<input type="checkbox" autocomplete="off"/></label>
@@ -84,6 +87,7 @@
84
87
  <% end %>
85
88
  </table>
86
89
  <% end %>
90
+ </div>
87
91
  <div class="footer">
88
92
  lots of love, from <a href="http://www.merbivore.com">merb</a>
89
93
  </div>
@@ -53,9 +53,9 @@ module Merb
53
53
  "you may need to check your Rackup file, see the Problems " \
54
54
  "section at: http://wiki.merbivore.com/pages/rack-middleware"
55
55
  end
56
-
57
- if klass == Application
58
- raise NotFound, "The 'Application' controller has no public actions"
56
+
57
+ if klass.abstract?
58
+ raise NotFound, "The '#{klass}' controller has no public actions"
59
59
  end
60
60
 
61
61
  controller = dispatch_action(klass, params[:action])
@@ -41,7 +41,7 @@ module Merb
41
41
  "Route matched, but route did not specify a controller.\n" +
42
42
  "Did you forgot to add :controller => \"people\" or :controller " +
43
43
  "segment to route definition?\nHere is what's specified:\n" +
44
- request.route_params.inspect
44
+ route.inspect
45
45
  end
46
46
  path = [params[:namespace], params[:controller]].compact.join("/")
47
47
  controller = path.snake_case.to_const_string
@@ -95,7 +95,49 @@ module Merb
95
95
  # into request params hash.
96
96
  def find_route!
97
97
  @route, @route_params = Merb::Router.route_for(self)
98
- @params.merge! @route_params
98
+ params.merge! @route_params
99
+ end
100
+
101
+ # Processes the return value of a deferred router block
102
+ # and returns the current route params for the current
103
+ # request evaluation
104
+ # ---
105
+ # @private
106
+ def _process_block_return(retval)
107
+ # If the return value is an array, then it is a redirect
108
+ # so we must set the request as a redirect and extract
109
+ # the redirect params and return it as a hash so that the
110
+ # dispatcher can handle it
111
+ if retval.is_a?(Array)
112
+ redirects!
113
+ return { :url => retval[0], :status => retval[1] }
114
+ end
115
+ retval
116
+ end
117
+
118
+ # Sets the request as a redirect. This method is only really
119
+ # used in the router to tell the request object how to handle
120
+ # the route params. This will also set the request as matched.
121
+ # ---
122
+ # @private
123
+ def redirects!
124
+ @matched = true
125
+ @redirects = true
126
+ end
127
+
128
+ # Sets the request as matched. This will abort evaluating any
129
+ # further deferred procs.
130
+ # ---
131
+ # @private
132
+ def matched!
133
+ @matched = true
134
+ end
135
+
136
+ # Checks whether or not the request has been matched to a route.
137
+ # ---
138
+ # @private
139
+ def matched?
140
+ @matched
99
141
  end
100
142
 
101
143
  # Redirect status of route matched this request.
@@ -104,7 +146,7 @@ module Merb
104
146
  # Integer::
105
147
  # The URL to redirect to if the route redirects
106
148
  def redirect_status
107
- route.redirect_status
149
+ @route_params[:status] if redirects?
108
150
  end
109
151
 
110
152
  # Returns redirect url of route matched this request.
@@ -112,7 +154,7 @@ module Merb
112
154
  # ==== Returns
113
155
  # <String>:: redirect url of route matched this request
114
156
  def redirect_url
115
- route.redirect_url
157
+ @route_params[:url] if redirects?
116
158
  end
117
159
 
118
160
  # Returns true if matched route does immediate redirection.
@@ -120,7 +162,7 @@ module Merb
120
162
  # ==== Returns
121
163
  # <Boolean>:: if matched route does immediate redirection.
122
164
  def redirects?
123
- route.redirects?
165
+ @redirects
124
166
  end
125
167
 
126
168
  private
@@ -271,10 +313,10 @@ module Merb
271
313
 
272
314
  # ==== Returns
273
315
  # String::
274
- # The protocol, i.e. either "https://" or "http://" depending on the
316
+ # The protocol, i.e. either "https" or "http" depending on the
275
317
  # HTTPS header.
276
318
  def protocol
277
- ssl? ? 'https://' : 'http://'
319
+ ssl? ? 'https' : 'http'
278
320
  end
279
321
 
280
322
  # ==== Returns
@@ -292,7 +334,7 @@ module Merb
292
334
  # ==== Returns
293
335
  # String:: The full URI, including protocol and host
294
336
  def full_uri
295
- protocol + host + uri
337
+ protocol + "://" + host + uri
296
338
  end
297
339
 
298
340
  # ==== Returns
@@ -535,7 +577,12 @@ module Merb
535
577
  query = preserve_order ? Dictionary.new : {}
536
578
  for pair in (query_string || '').split(/[#{delimiter}] */n)
537
579
  key, value = unescape(pair).split('=',2)
538
- normalize_params(query, key, value)
580
+ next if key.nil?
581
+ if key.include?('[')
582
+ normalize_params(query, key, value)
583
+ else
584
+ query[key] = value
585
+ end
539
586
  end
540
587
  preserve_order ? query : query.to_mash
541
588
  end
@@ -1,7 +1,8 @@
1
1
  require 'merb-core/dispatch/router/cached_proc'
2
2
  require 'merb-core/dispatch/router/behavior'
3
+ require 'merb-core/dispatch/router/resources'
3
4
  require 'merb-core/dispatch/router/route'
4
- require 'merb-core/controller/mixins/responder'
5
+
5
6
  module Merb
6
7
  # Router stores route definitions and finds the first
7
8
  # route that matches the incoming request URL.
@@ -20,19 +21,69 @@ module Merb
20
21
  #
21
22
  # Compilation is synchronized by mutex.
22
23
  class Router
23
- SEGMENT_REGEXP = /(:([a-z_][a-z0-9_]*|:))/
24
- SEGMENT_REGEXP_WITH_BRACKETS = /(:[a-z_]+)(\[(\d+)\])?/
25
- JUST_BRACKETS = /\[(\d+)\]/
26
- PARENTHETICAL_SEGMENT_STRING = "([^\/.,;?]+)".freeze
24
+ @routes = []
25
+ @named_routes = {}
26
+ @resource_routes = {}
27
+ @compiler_mutex = Mutex.new
28
+ @root_behavior = Behavior.new.defaults(:action => "index")
27
29
 
28
- @@named_routes = {}
29
- @@routes = []
30
- @@compiler_mutex = Mutex.new
31
- cattr_accessor :routes, :named_routes
30
+ # Raised when route lookup fails.
31
+ class RouteNotFound < StandardError; end;
32
+ # Raised when parameters given to generation
33
+ # method do not match route parameters.
34
+ class GenerationError < StandardError; end;
35
+ class NotCompiledError < StandardError; end;
32
36
 
33
37
  class << self
34
- # Finds route matching URI of the request and
35
- # returns a tuple of [route index, route params].
38
+ # @private
39
+ attr_accessor :routes, :named_routes, :resource_routes, :root_behavior
40
+
41
+ # Creates a route building context and evaluates the block in it. A
42
+ # copy of +root_behavior+ (and instance of Behavior) is copied as
43
+ # the context.
44
+ #
45
+ # ==== Parameters
46
+ # first<Array>::
47
+ # An array containing routes that should be prepended to the routes
48
+ # defined in the block.
49
+ #
50
+ # last<Array>::
51
+ # An array containing routes that should be appended to the routes
52
+ # defined in the block.
53
+ #
54
+ # ==== Returns
55
+ # Merb::Router::
56
+ # Returns self to allow chaining of methods.
57
+ def prepare(first = [], last = [], &block)
58
+ @routes = []
59
+ root_behavior._with_proxy(&block)
60
+ @routes = first + @routes + last
61
+ compile
62
+ self
63
+ end
64
+
65
+ # Appends route in the block to routing table.
66
+ def append(&block)
67
+ prepare(routes, [], &block)
68
+ end
69
+
70
+ # Prepends routes in the block to routing table.
71
+ def prepend(&block)
72
+ prepare([], routes, &block)
73
+ end
74
+
75
+ # Clears the routing table. Route generation and request matching
76
+ # won't work anymore until a new routing table is built.
77
+ def reset!
78
+ class << self
79
+ alias_method :match, :match_before_compilation
80
+ end
81
+ self.routes, self.named_routes = [], {}
82
+ end
83
+
84
+ # Finds route matching URI of the request and returns a tuple of
85
+ # [route index, route params]. This method is called by the
86
+ # dispatcher and isn't as useful in applications.
36
87
  #
37
88
  # ==== Parameters
38
89
  # request<Merb::Request>:: request to match.
@@ -42,7 +93,10 @@ module Merb
42
93
  # Two-tuple: route index and route parameters. Route
43
94
  # parameters are :controller, :action and all the named
44
95
  # segments of the route.
45
- def route_for(request)
96
+ #
97
+ # ---
98
+ # @private
99
+ def route_for(request) #:nodoc:
46
100
  index, params = match(request)
47
101
  route = routes[index] if index
48
102
  if !route
@@ -51,152 +105,124 @@ module Merb
51
105
  end
52
106
  [route, params]
53
107
  end
54
-
55
- # Clear all routes.
56
- def reset!
57
- self.routes, self.named_routes = [], {}
58
- end
59
108
 
60
- # Appends the generated routes to the current routes.
61
- #
62
- # ==== Parameters
63
- # &block::
64
- # A block that generates new routes when yielded a new Behavior.
65
- def append(&block)
66
- prepare(@@routes, [], &block)
109
+ # Just a placeholder for the compiled match method
110
+ def match_before_compilation(request) #:nodoc:
111
+ raise NotCompiledError, "The routes have not been compiled yet"
67
112
  end
68
113
 
69
- # Prepends the generated routes to the current routes.
114
+ alias_method :match, :match_before_compilation
115
+
116
+ # Generates a URL from the params
70
117
  #
71
118
  # ==== Parameters
72
- # &block::
73
- # A block that generates new routes when yielded a new Behavior.
74
- def prepend(&block)
75
- prepare([], @@routes, &block)
76
- end
77
-
78
- # Prepares new routes and adds them to existing routes.
119
+ # name<Symbol>::
120
+ # The name of the route to generate
79
121
  #
80
- # ==== Parameters
81
- # first<Array>:: An array of routes to add before the generated routes.
82
- # last<Array>:: An array of routes to add after the generated routes.
83
- # &block:: A block that generates new routes.
122
+ # anonymous_params<Object>::
123
+ # An array of anonymous parameters to generate the route
124
+ # with. These parameters are assigned to the route parameters
125
+ # in the order that they are passed.
84
126
  #
85
- # ==== Block parameters (&block)
86
- # new_behavior<Behavior>:: Behavior for child routes.
87
- def prepare(first = [], last = [], &block)
88
- @@routes = []
89
- yield Behavior.new({}, { :action => 'index' }) # defaults
90
- @@routes = first + @@routes + last
91
- compile
92
- end
93
-
94
- # Capture any new routes that have been added within the block.
95
- #
96
- # This utility method lets you track routes that have been added;
97
- # it doesn't affect how/which routes are added.
127
+ # params<Hash>::
128
+ # Named parameters to generate the route with.
98
129
  #
99
- # &block:: A context in which routes are generated.
100
- def capture(&block)
101
- routes_before, named_route_keys_before = self.routes.dup, self.named_routes.keys
102
- yield
103
- [self.routes - routes_before, self.named_routes.except(*named_route_keys_before)]
104
- end
105
-
130
+ # defaults<Hash>::
131
+ # A hash of default parameters to generate the route with.
132
+ # This is usually the request parameters. If there are any
133
+ # required params that are missing to generate the route,
134
+ # they are pulled from this hash.
106
135
  # ==== Returns
107
- # String:: A routing lambda statement generated from the routes.
108
- def compiled_statement
109
- @@compiler_mutex.synchronize do
110
- @@compiled_statement = "def match(request)\n"
111
- @@compiled_statement << " params = request.params\n"
112
- @@compiled_statement << " cached_path = request.path\n cached_method = request.method.to_s\n "
113
- @@routes.each_with_index { |route, i| @@compiled_statement << route.compile(i == 0) }
114
- @@compiled_statement << " else\n [nil, {}]\n"
115
- @@compiled_statement << " end\n"
116
- @@compiled_statement << "end"
136
+ # String:: The generated URL
137
+ # ---
138
+ # @private
139
+ def url(name, *args)
140
+ unless name.is_a?(Symbol)
141
+ args.unshift(name)
142
+ name = :default
117
143
  end
118
- end
119
144
 
120
- # Defines the match function for this class based on the
121
- # compiled_statement.
122
- def compile
123
- puts "compiled route: #{compiled_statement}" if $DEBUG
124
- eval(compiled_statement, binding, "Generated Code for Router#match(#{__FILE__}:#{__LINE__})", 1)
145
+ unless route = Merb::Router.named_routes[name]
146
+ raise Merb::Router::GenerationError, "Named route not found: #{name}"
147
+ end
148
+
149
+ defaults = args.pop
150
+
151
+ route.generate(args, defaults)
125
152
  end
126
-
127
- # Generates a URL based on passed options.
153
+
154
+ # Generates a URL from the resource(s)
128
155
  #
129
156
  # ==== Parameters
130
- # name<~to_sym, Hash>:: The name of the route to generate.
131
- # params<Hash, Fixnum, Object>:: The params to use in the route generation.
132
- # fallback<Hash>:: Parameters for generating a fallback URL.
157
+ # resources<Symbol,Object>::
158
+ # The identifiers for the resource route to generate. These
159
+ # can either be symbols or objects. Symbols denote resource
160
+ # collection routes and objects denote the members.
133
161
  #
162
+ # params<Hash>::
163
+ # Any extra parameters needed to generate the route.
134
164
  # ==== Returns
135
- # String:: The generated URL.
136
- #
137
- # ==== Alternatives
138
- # If name is a hash, it will be merged with params and passed on to
139
- # generate_for_default_route along with fallback.
140
- def generate(name, params = {}, fallback = {})
141
- params.reject! { |k,v| v.nil? } if params.is_a? Hash
142
- if name.is_a? Hash
143
- name.reject! { |k,v| v.nil? }
144
- return generate_for_default_route(name.merge(params), fallback)
165
+ # String:: The generated URL
166
+ # ---
167
+ # @private
168
+ def resource(*args)
169
+ defaults = args.pop
170
+ options = extract_options_from_args!(args) || {}
171
+ key = []
172
+ params = []
173
+
174
+ args.each do |arg|
175
+ if arg.is_a?(Symbol) || arg.is_a?(String)
176
+ key << arg.to_s
177
+ else
178
+ key << arg.class.to_s
179
+ params << arg
180
+ end
145
181
  end
146
- name = name.to_sym
147
- unless @@named_routes.key? name
148
- raise "Named route not found: #{name}"
149
- else
150
- @@named_routes[name].generate(params, fallback)
182
+
183
+ params << options
184
+
185
+ unless route = Merb::Router.resource_routes[key]
186
+ raise Merb::Router::GenerationError, "Resource route not found: #{args.inspect}"
151
187
  end
188
+
189
+ route.generate(params, defaults)
152
190
  end
153
191
 
154
- # Generates a URL based on the default route scheme of
155
- # "/:controller/:action/:id.:format".
156
- #
157
- # ==== Parameters
158
- # params<Hash>::
159
- # The primary parameters to create the route from (see below).
160
- # fallback<Hash>:: Fallback parameters. Same options as params.
161
- #
162
- # ==== Options (params)
163
- # :controller<~to_s>:: The controller name. Required.
164
- # :action<~to_s>:: The action name. Required.
165
- # :id<~to_s>:: The ID for use in the action.
166
- # :format<~to_s>:: The format of the preferred response.
167
- #
168
- # ==== Returns
169
- # String:: The generated URL.
170
- def generate_for_default_route(params, fallback)
171
- query_params = params.reject do |k,v|
172
- [:controller, :action, :id, :format, :fragment].include?(k.to_sym)
192
+ private
193
+
194
+ # Defines method with a switch statement that does routes recognition.
195
+ def compile
196
+ if routes.any?
197
+ eval(compiled_statement, binding, "Generated Code for Router", 1)
198
+ else
199
+ reset!
173
200
  end
201
+ end
174
202
 
175
- controller = params[:controller] || fallback[:controller]
176
- raise "Controller Not Specified" unless controller
177
- url = "/#{controller}"
203
+ # Generates method that does route recognition with a switch statement.
204
+ def compiled_statement
205
+ @compiler_mutex.synchronize do
206
+ condition_keys, if_statements = Set.new, ""
178
207
 
179
- if params[:action] || params[:id] || params[:format] || !query_params.empty?
180
- action = params[:action] || fallback[:action]
181
- raise "Action Not Specified" unless action
182
- url += "/#{action}"
183
- end
184
- if params[:id]
185
- url += "/#{params[:id]}"
186
- end
187
- if format = params[:format]
188
- format = fallback[:format] if format == :current
189
- url += ".#{format}"
190
- end
191
- unless query_params.empty?
192
- url += "?" + Merb::Request.params_to_query_string(query_params)
193
- end
194
- if params[:fragment]
195
- url += "##{params[:fragment]}"
208
+ routes.each_with_index do |route, i|
209
+ route.freeze
210
+ route.conditions.keys.each { |key| condition_keys << key }
211
+ if_statements << route.compiled_statement(i == 0)
212
+ end
213
+
214
+ statement = "def match(request)\n"
215
+ statement << condition_keys.inject("") do |cached, key|
216
+ cached << " cached_#{key} = request.#{key}.to_s\n"
217
+ end
218
+ statement << if_statements
219
+ statement << " else\n"
220
+ statement << " [nil, {}]\n"
221
+ statement << " end\n"
222
+ statement << "end"
196
223
  end
197
- url
198
224
  end
199
- end # self
200
225
 
226
+ end # class << self
201
227
  end
202
228
  end