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,303 @@
1
+ require "optparse"
2
+ require "yaml"
3
+
4
+ module Merb
5
+
6
+ class Config
7
+
8
+ class << self
9
+
10
+ # ==== Returns
11
+ # Hash:: The defaults for the config.
12
+ def defaults
13
+ @defaults ||= {
14
+ :host => "0.0.0.0",
15
+ :port => "4000",
16
+ :adapter => "runner",
17
+ :reload_classes => true,
18
+ :environment => "development",
19
+ :merb_root => Dir.pwd,
20
+ :use_mutex => true,
21
+ :session_id_key => "_session_id",
22
+ :log_delimiter => " ~ ",
23
+ :log_auto_flush => false,
24
+ :log_level => :info,
25
+ :disabled_components => [],
26
+ :deferred_actions => [],
27
+ :verbose => false
28
+ }
29
+ end
30
+
31
+ # Yields the configuration.
32
+ #
33
+ # ==== Block parameters
34
+ # c<Hash>:: The configuration parameters.
35
+ #
36
+ # ==== Examples
37
+ # Merb::Config.use do |config|
38
+ # config[:exception_details] = false
39
+ # end
40
+ def use
41
+ @configuration ||= {}
42
+ yield @configuration
43
+ end
44
+
45
+ # ==== Parameters
46
+ # key<Object>:: The key to check.
47
+ #
48
+ # ==== Returns
49
+ # Boolean:: True if the key exists in the config.
50
+ def key?(key)
51
+ @configuration.key?(key)
52
+ end
53
+
54
+ # ==== Parameters
55
+ # key<Object>:: The key to retrieve the parameter for.
56
+ #
57
+ # ==== Returns
58
+ # Object:: The value of the configuration parameter.
59
+ def [](key)
60
+ (@configuration||={})[key]
61
+ end
62
+
63
+ # ==== Parameters
64
+ # key<Object>:: The key to set the parameter for.
65
+ # val<Object>:: The value of the parameter.
66
+ def []=(key,val)
67
+ @configuration[key] = val
68
+ end
69
+
70
+ # ==== Parameters
71
+ # key<Object>:: The key of the parameter to delete.
72
+ def delete(key)
73
+ @configuration.delete(key)
74
+ end
75
+
76
+ # ==== Parameters
77
+ # key<Object>:: The key to retrieve the parameter for.
78
+ # default<Object>::
79
+ # The default value to return if the parameter is not set.
80
+ #
81
+ # ==== Returns
82
+ # Object:: The value of the configuration parameter or the default.
83
+ def fetch(key, default)
84
+ @configuration.fetch(key, default)
85
+ end
86
+
87
+ # ==== Returns
88
+ # Hash:: The config as a hash.
89
+ def to_hash
90
+ @configuration
91
+ end
92
+
93
+ # ==== Returns
94
+ # String:: The config as YAML.
95
+ def to_yaml
96
+ @configuration.to_yaml
97
+ end
98
+
99
+ # Sets up the configuration by storing the given settings.
100
+ #
101
+ # ==== Parameters
102
+ # settings<Hash>::
103
+ # Configuration settings to use. These are merged with the defaults.
104
+ def setup(settings = {})
105
+ @configuration = defaults.merge(settings)
106
+ end
107
+
108
+ # Parses the command line arguments and stores them in the config.
109
+ #
110
+ # ==== Parameters
111
+ # argv<String>:: The command line arguments. Defaults to +ARGV+.
112
+ def parse_args(argv = ARGV)
113
+ @configuration ||= {}
114
+ # Our primary configuration hash for the length of this method
115
+ options = {}
116
+
117
+ # Environment variables always win
118
+ options[:environment] = ENV["MERB_ENV"] if ENV["MERB_ENV"]
119
+
120
+ # Build a parser for the command line arguments
121
+ opts = OptionParser.new do |opts|
122
+ opts.version = Merb::VERSION
123
+ opts.release = Merb::RELEASE
124
+
125
+ opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]"
126
+ opts.define_head "Merb. Pocket rocket web framework"
127
+ opts.separator '*'*80
128
+ opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
129
+ opts.separator '*'*80
130
+
131
+ opts.on("-u", "--user USER", "This flag is for having merb run as a user other than the one currently logged in. Note: if you set this you must also provide a --group option for it to take effect.") do |user|
132
+ options[:user] = user
133
+ end
134
+
135
+ opts.on("-G", "--group GROUP", "This flag is for having merb run as a group other than the one currently logged in. Note: if you set this you must also provide a --user option for it to take effect.") do |group|
136
+ options[:group] = group
137
+ end
138
+
139
+ opts.on("-d", "--daemonize", "This will run a single merb in the background.") do |daemon|
140
+ options[:daemonize] = true
141
+ end
142
+
143
+ opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run.") do |nodes|
144
+ options[:cluster] = nodes
145
+ end
146
+
147
+ opts.on("-I", "--init-file FILE", "File to use for initialization on load, defaults to config/init.rb") do |init_file|
148
+ options[:init_file] = init_file
149
+ end
150
+
151
+ opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
152
+ options[:port] = port
153
+ end
154
+
155
+ opts.on("-o", "--socket-file FILE", "Socket file to run merb on, defaults to [Merb.root]/log/merb.sock") do |port|
156
+ options[:socket_file] = port
157
+ end
158
+
159
+ opts.on("-s", "--socket SOCKNUM", "Socket number to run merb on, defaults to 0.") do |port|
160
+ options[:socket] = port
161
+ end
162
+
163
+ opts.on("-P", "--pid PIDFILE", "PID file, defaults to [Merb.root]/log/merb.[port_number].pid") do |pid_file|
164
+ options[:pid_file] = pid_file
165
+ end
166
+
167
+ opts.on("-h", "--host HOSTNAME", "Host to bind to (default is 0.0.0.0).") do |host|
168
+ options[:host] = host
169
+ end
170
+
171
+ opts.on("-m", "--merb-root /path/to/approot", "The path to the Merb.root for the app you want to run (default is current working dir).") do |root|
172
+ options[:merb_root] = File.expand_path(root)
173
+ end
174
+
175
+ opts.on("-a", "--adapter mongrel", "The rack adapter to use to run merb[mongrel, emongrel, thin, ebb, fastcgi, webrick, runner, irb]") do |adapter|
176
+ options[:adapter] = adapter
177
+ end
178
+
179
+ opts.on("-R", "--rackup FILE", "Load an alternate Rack config file (default is config/rack.rb)") do |rackup|
180
+ options[:rackup] = rackup
181
+ end
182
+
183
+ opts.on("-i", "--irb-console", "This flag will start merb in irb console mode. All your models and other classes will be available for you in an irb session.") do |console|
184
+ options[:adapter] = 'irb'
185
+ end
186
+
187
+ opts.on("-S", "--sandbox", "This flag will enable a sandboxed irb console. If your ORM supports transactions, all edits will be rolled back on exit.") do |sandbox|
188
+ options[:sandbox] = true
189
+ end
190
+
191
+ opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of these options: debug < info < warn < error < fatal") do |log_level|
192
+ options[:log_level] = log_level.to_sym
193
+ end
194
+
195
+ opts.on("-L", "--log LOGFILE", "A string representing the logfile to use.") do |log_file|
196
+ options[:log_file] = log_file
197
+ end
198
+
199
+ opts.on("-e", "--environment STRING", "Run merb in the correct mode(development, production, testing)") do |env|
200
+ options[:environment] = env
201
+ end
202
+
203
+ opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
204
+ "Command-line option to run scripts and/or code in the merb app.") do |code_or_file|
205
+ options[:runner_code] = code_or_file
206
+ options[:adapter] = 'runner'
207
+ end
208
+
209
+ opts.on("-K", "--graceful PORT or all", "Gracefully kill one merb proceses by port number. Use merb -K all to gracefully kill all merbs.") do |ports|
210
+ options[:action] = :kill
211
+ options[:port] = ports
212
+ end
213
+
214
+ opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. Use merb -k all to kill all merbs.") do |port|
215
+ options[:action] = :kill_9
216
+ options[:port] = port
217
+ end
218
+
219
+ opts.on("-X", "--mutex on/off", "This flag is for turning the mutex lock on and off.") do |mutex|
220
+ if mutex == "off"
221
+ options[:use_mutex] = false
222
+ else
223
+ options[:use_mutex] = true
224
+ end
225
+ end
226
+
227
+ opts.on("-D", "--debugger", "Run merb using rDebug.") do
228
+ begin
229
+ require "ruby-debug"
230
+ Debugger.start
231
+ Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
232
+ puts "Debugger enabled"
233
+ rescue LoadError
234
+ puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
235
+ exit
236
+ end
237
+ end
238
+
239
+ opts.on("-V", "--verbose", "Print extra information") do
240
+ options[:verbose] = true
241
+ end
242
+
243
+ opts.on("-?", "-H", "--help", "Show this help message") do
244
+ puts opts
245
+ exit
246
+ end
247
+ end
248
+
249
+ # Parse what we have on the command line
250
+ opts.parse!(argv)
251
+ Merb::Config.setup(options)
252
+ end
253
+
254
+ attr_accessor :configuration
255
+
256
+ # Set configuration parameters from a code block, where each method
257
+ # evaluates to a config parameter.
258
+ #
259
+ # ==== Parameters
260
+ # &block:: Configuration parameter block.
261
+ #
262
+ # ==== Examples
263
+ # # Set environment and log level.
264
+ # Merb::Config.configure do
265
+ # environment "development"
266
+ # log_level "debug"
267
+ # end
268
+ def configure(&block)
269
+ ConfigBlock.new(self, &block) if block_given?
270
+ end
271
+
272
+ # Allows retrieval of single key config values via Merb.config.<key>
273
+ # Allows single key assignment via Merb.config.<key> = ...
274
+ #
275
+ # ==== Parameters
276
+ # method<~to_s>:: Method name as hash key value.
277
+ # *args:: Value to set the configuration parameter to.
278
+ def method_missing(method, *args)
279
+ if method.to_s[-1,1] == '='
280
+ @configuration[method.to_s.tr('=','').to_sym] = *args
281
+ else
282
+ @configuration[method]
283
+ end
284
+ end
285
+
286
+ end # class << self
287
+
288
+ class ConfigBlock
289
+
290
+ def initialize(klass, &block)
291
+ @klass = klass
292
+ instance_eval(&block)
293
+ end
294
+
295
+ def method_missing(method, *args)
296
+ @klass[method] = *args
297
+ end
298
+
299
+ end # class Configurator
300
+
301
+ end # Config
302
+
303
+ end # Merb
@@ -0,0 +1,43 @@
1
+ # Most of this list is simply constants frozen for efficiency
2
+ module Merb
3
+ module Const
4
+
5
+ DEFAULT_SEND_FILE_OPTIONS = {
6
+ :type => 'application/octet-stream'.freeze,
7
+ :disposition => 'attachment'.freeze
8
+ }.freeze
9
+
10
+ SET_COOKIE = " %s=%s; path=/; expires=%s".freeze
11
+ COOKIE_EXPIRATION_FORMAT = "%a, %d-%b-%Y %H:%M:%S GMT".freeze
12
+ COOKIE_SPLIT = /[;,] */n.freeze
13
+ COOKIE_REGEXP = /\s*(.+)=(.*)\s*/.freeze
14
+ COOKIE_EXPIRED_TIME = Time.at(0).freeze
15
+ HOUR = 60 * 60
16
+ DAY = HOUR * 24
17
+ WEEK = DAY * 7
18
+ MULTIPART_REGEXP = /\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze
19
+ HTTP_COOKIE = 'HTTP_COOKIE'.freeze
20
+ QUERY_STRING = 'QUERY_STRING'.freeze
21
+ JSON_MIME_TYPE_REGEXP = %r{^application/json|^text/x-json}.freeze
22
+ XML_MIME_TYPE_REGEXP = %r{^application/xml|^text/xml}.freeze
23
+ FORM_URL_ENCODED_REGEXP = %r{^application/x-www-form-urlencoded}.freeze
24
+ UPCASE_CONTENT_TYPE = 'CONTENT_TYPE'.freeze
25
+ CONTENT_TYPE = "Content-Type".freeze
26
+ LAST_MODIFIED = "Last-Modified".freeze
27
+ SLASH = "/".freeze
28
+ REQUEST_METHOD = "REQUEST_METHOD".freeze
29
+ GET = "GET".freeze
30
+ POST = "POST".freeze
31
+ HEAD = "HEAD".freeze
32
+ CONTENT_LENGTH = "CONTENT_LENGTH".freeze
33
+ HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
34
+ HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
35
+ HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
36
+ UPLOAD_ID = "upload_id".freeze
37
+ PATH_INFO = "PATH_INFO".freeze
38
+ SCRIPT_NAME = "SCRIPT_NAME".freeze
39
+ REQUEST_URI = "REQUEST_URI".freeze
40
+ REQUEST_PATH = "REQUEST_PATH".freeze
41
+ REMOTE_ADDR = "REMOTE_ADDR".freeze
42
+ end
43
+ end
@@ -0,0 +1,578 @@
1
+ # ==== Why do we use Underscores?
2
+ # In Merb, views are actually methods on controllers. This provides
3
+ # not-insignificant speed benefits, as well as preventing us from
4
+ # needing to copy over instance variables, which we think is proof
5
+ # that everything belongs in one class to begin with.
6
+ #
7
+ # Unfortunately, this means that view helpers need to be included
8
+ # into the <strong>Controller</strong> class. To avoid causing confusion
9
+ # when your helpers potentially conflict with our instance methods,
10
+ # we use an _ to disambiguate. As long as you don't begin your helper
11
+ # methods with _, you only need to worry about conflicts with Merb
12
+ # methods that are part of the public API.
13
+ #
14
+ #
15
+ #
16
+ # ==== Filters
17
+ # #before is a class method that allows you to specify before filters in
18
+ # your controllers. Filters can either be a symbol or string that
19
+ # corresponds to a method name to call, or a proc object. if it is a method
20
+ # name that method will be called and if it is a proc it will be called
21
+ # with an argument of self where self is the current controller object.
22
+ # When you use a proc as a filter it needs to take one parameter.
23
+ #
24
+ # #after is identical, but the filters are run after the action is invoked.
25
+ #
26
+ # ===== Examples
27
+ # before :some_filter
28
+ # before :authenticate, :exclude => [:login, :signup]
29
+ # before :has_role, :with => ["Admin"], :exclude => [:index,:show]
30
+ # before Proc.new {|c| c.some_method }, :only => :foo
31
+ # before :authorize, :unless => logged_in?
32
+ #
33
+ # You can use either :only => :actionname or :exclude => [:this, :that]
34
+ # but not both at once. :only will only run before the listed actions
35
+ # and :exclude will run for every action that is not listed.
36
+ #
37
+ # Merb's before filter chain is very flexible. To halt the filter chain you
38
+ # use throw :halt. If throw is called with only one argument of :halt the
39
+ # return of the method filters_halted will be what is rendered to the view.
40
+ # You can overide filters_halted in your own controllers to control what it
41
+ # outputs. But the throw construct is much more powerful then just that.
42
+ # throw :halt can also take a second argument. Here is what that second arg
43
+ # can be and the behavior each type can have:
44
+ #
45
+ # * +String+:
46
+ # when the second arg is a string then that string will be what
47
+ # is rendered to the browser. Since merb's render method returns
48
+ # a string you can render a template or just use a plain string:
49
+ #
50
+ # throw :halt, "You don't have permissions to do that!"
51
+ # throw :halt, render(:action => :access_denied)
52
+ #
53
+ # * +Symbol+:
54
+ # If the second arg is a symbol then the method named after that
55
+ # symbol will be called
56
+ #
57
+ # throw :halt, :must_click_disclaimer
58
+ #
59
+ # * +Proc+:
60
+ #
61
+ # If the second arg is a Proc, it will be called and its return
62
+ # value will be what is rendered to the browser:
63
+ #
64
+ # throw :halt, proc {|c| c.access_denied }
65
+ # throw :halt, proc {|c| Tidy.new(c.index) }
66
+ #
67
+ # ===== Filter Options (.before, .after, .add_filter, .if, .unless)
68
+ # :only<Symbol, Array[Symbol]>::
69
+ # A list of actions that this filter should apply to
70
+ #
71
+ # :exclude<Symbol, Array[Symbol]::
72
+ # A list of actions that this filter should *not* apply to
73
+ #
74
+ # :if<Symbol, Proc>::
75
+ # Only apply the filter if the method named after the symbol or calling the proc evaluates to true
76
+ #
77
+ # :unless<Symbol, Proc>::
78
+ # Only apply the filter if the method named after the symbol or calling the proc evaluates to false
79
+ #
80
+ # ===== Types (shortcuts for use in this file)
81
+ # Filter:: <Array[Symbol, (Symbol, String, Proc)]>
82
+ #
83
+ # ==== params[:action] and params[:controller] deprecated
84
+ # params[:action] and params[:controller] have been deprecated as of
85
+ # the 0.9.0 release. They are no longer set during dispatch, and
86
+ # have been replaced by action_name and controller_name respectively.
87
+ class Merb::AbstractController
88
+ include Merb::RenderMixin
89
+ include Merb::InlineTemplates
90
+
91
+ class_inheritable_accessor :_layout, :_template_root, :template_roots
92
+ class_inheritable_accessor :_before_filters, :_after_filters
93
+
94
+ FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
95
+
96
+ # ==== Returns
97
+ # String:: The controller name in path form, e.g. "admin/items".
98
+ #---
99
+ # @public
100
+ def self.controller_name() @controller_name ||= self.name.to_const_path end
101
+
102
+ # ==== Returns
103
+ # String:: The controller name in path form, e.g. "admin/items".
104
+ def controller_name() self.class.controller_name end
105
+
106
+ self._before_filters, self._after_filters = [], []
107
+
108
+ # This is called after the controller is instantiated to figure out where to
109
+ # for templates under the _template_root. Override this to define a new
110
+ # structure for your app.
111
+ #
112
+ # ==== Parameters
113
+ # context<~to_s>:: The controller context (the action or template name).
114
+ # type<~to_s>:: The content type. Defaults to nil.
115
+ # controller<~to_s>::
116
+ # The name of the controller. Defaults to controller_name.
117
+ #
118
+ #
119
+ # ==== Returns
120
+ # String::
121
+ # Indicating where to look for the template for the current controller,
122
+ # context, and content-type.
123
+ #
124
+ # ==== Notes
125
+ # The type is irrelevant for controller-types that don't support
126
+ # content-type negotiation, so we default to not include it in the
127
+ # superclass.
128
+ #
129
+ # ==== Examples
130
+ # def _template_location
131
+ # "#{params[:controller]}.#{params[:action]}.#{content_type}"
132
+ # end
133
+ #
134
+ # This would look for templates at controller.action.mime.type instead
135
+ # of controller/action.mime.type
136
+ #---
137
+ # @public
138
+ def _template_location(context, type = nil, controller = controller_name)
139
+ controller ? "#{controller}/#{context}" : context
140
+ end
141
+
142
+ # The location to look for a template - stub method for particular behaviour.
143
+ #
144
+ # ==== Parameters
145
+ # template<String>:: The absolute path to a template - without template extension.
146
+ # type<~to_s>::
147
+ # The mime-type of the template that will be rendered. Defaults to nil.
148
+ #
149
+ # @public
150
+ def _absolute_template_location(template, type)
151
+ template
152
+ end
153
+
154
+ def self._template_root=(root)
155
+ @_template_root = root
156
+ _reset_template_roots
157
+ end
158
+
159
+ def self._reset_template_roots
160
+ self.template_roots = [[self._template_root, :_template_location]]
161
+ end
162
+
163
+ # ==== Returns
164
+ # roots<Array[Array]>::
165
+ # Template roots as pairs of template root path and template location
166
+ # method.
167
+ def self._template_roots
168
+ self.template_roots || _reset_template_roots
169
+ end
170
+
171
+ # ==== Parameters
172
+ # roots<Array[Array]>::
173
+ # Template roots as pairs of template root path and template location
174
+ # method.
175
+ def self._template_roots=(roots)
176
+ self.template_roots = roots
177
+ end
178
+
179
+ cattr_accessor :_abstract_subclasses, :_template_path_cache
180
+ #---
181
+ # We're using abstract_subclasses so that Merb::Controller can have its
182
+ # own subclasses. We're using a Set so we don't have to worry about
183
+ # uniqueness.
184
+ self._abstract_subclasses = Set.new
185
+
186
+ # ==== Returns
187
+ # Set:: The subclasses.
188
+ def self.subclasses_list() _abstract_subclasses end
189
+
190
+ class << self
191
+ # ==== Parameters
192
+ # klass<Merb::AbstractController>::
193
+ # The controller that is being inherited from Merb::AbstractController
194
+ def inherited(klass)
195
+ _abstract_subclasses << klass.to_s
196
+ helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper"
197
+ Object.make_module helper_module_name
198
+ klass.class_eval <<-HERE
199
+ include Object.full_const_get("#{helper_module_name}") rescue nil
200
+ HERE
201
+ super
202
+ end
203
+ end
204
+
205
+ attr_accessor :_benchmarks, :_thrown_content
206
+
207
+ #---
208
+ # @semipublic
209
+ attr_accessor :body
210
+
211
+ attr_accessor :action_name
212
+
213
+ # ==== Parameters
214
+ # *args:: The args are ignored.
215
+ def initialize(*args)
216
+ @_benchmarks = {}
217
+ @_caught_content = {}
218
+ @_template_stack = []
219
+ end
220
+
221
+ # This will dispatch the request, calling setup_session and finalize_session
222
+ #
223
+ # ==== Parameters
224
+ # action<~to_s>::
225
+ # The action to dispatch to. This will be #send'ed in _call_action.
226
+ # Defaults to :to_s.
227
+ #
228
+ # ==== Raises
229
+ # MerbControllerError:: Invalid body content caught.
230
+ def _dispatch(action=:to_s)
231
+ setup_session
232
+ self.action_name = action
233
+
234
+ caught = catch(:halt) do
235
+ start = Time.now
236
+ result = _call_filters(_before_filters)
237
+ @_benchmarks[:before_filters_time] = Time.now - start if _before_filters
238
+ result
239
+ end
240
+
241
+ @body = case caught
242
+ when :filter_chain_completed then _call_action(action_name)
243
+ when String then caught
244
+ when nil then _filters_halted
245
+ when Symbol then __send__(caught)
246
+ when Proc then caught.call(self)
247
+ else
248
+ raise MerbControllerError, "The before filter chain is broken dude. wtf?"
249
+ end
250
+ start = Time.now
251
+ _call_filters(_after_filters)
252
+ @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
253
+ finalize_session
254
+ @body
255
+ end
256
+
257
+ # This method exists to provide an overridable hook for ActionArgs
258
+ #
259
+ # ==== Parameters
260
+ # action<~to_s>:: the action method to dispatch to
261
+ def _call_action(action)
262
+ send(action)
263
+ end
264
+
265
+ # ==== Parameters
266
+ # filter_set<Array[Filter]>::
267
+ # A set of filters in the form [[:filter, rule], [:filter, rule]]
268
+ #
269
+ # ==== Returns
270
+ # Symbol:: :filter_chain_completed.
271
+ #
272
+ # ==== Notes
273
+ # Filter rules can be Symbols, Strings, or Procs.
274
+ #
275
+ # Symbols or Strings::
276
+ # Call the method represented by the +Symbol+ or +String+.
277
+ # Procs::
278
+ # Execute the +Proc+, in the context of the controller (self will be the
279
+ # controller)
280
+ def _call_filters(filter_set)
281
+ (filter_set || []).each do |filter, rule|
282
+ if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
283
+ case filter
284
+ when Symbol, String
285
+ if rule.key?(:with)
286
+ args = rule[:with]
287
+ send(filter, *args)
288
+ else
289
+ send(filter)
290
+ end
291
+ when Proc then self.instance_eval(&filter)
292
+ end
293
+ end
294
+ end
295
+ return :filter_chain_completed
296
+ end
297
+
298
+ # ==== Parameters
299
+ # rule<Hash>:: Rules for the filter (see below).
300
+ # action_name<~to_s>:: The name of the action to be called.
301
+ #
302
+ # ==== Options (rule)
303
+ # :only<Array>::
304
+ # Optional list of actions to fire. If given, action_name must be a part of
305
+ # it for this function to return true.
306
+ # :exclude<Array>::
307
+ # Optional list of actions not to fire. If given, action_name must not be a
308
+ # part of it for this function to return true.
309
+ #
310
+ # ==== Returns
311
+ # Boolean:: True if the action should be called.
312
+ def _call_filter_for_action?(rule, action_name)
313
+ # Both:
314
+ # * no :only or the current action is in the :only list
315
+ # * no :exclude or the current action is not in the :exclude list
316
+ (!rule.key?(:only) || rule[:only].include?(action_name)) &&
317
+ (!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
318
+ end
319
+
320
+ # ==== Parameters
321
+ # rule<Hash>:: Rules for the filter (see below).
322
+ #
323
+ # ==== Options (rule)
324
+ # :if<Array>:: Optional conditions that must be met for the filter to fire.
325
+ # :unless<Array>::
326
+ # Optional conditions that must not be met for the filter to fire.
327
+ #
328
+ # ==== Returns
329
+ # Boolean:: True if the conditions are met.
330
+ def _filter_condition_met?(rule)
331
+ # Both:
332
+ # * no :if or the if condition evaluates to true
333
+ # * no :unless or the unless condition evaluates to false
334
+ (!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
335
+ (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
336
+ end
337
+
338
+ # ==== Parameters
339
+ # condition<Symbol, Proc>:: The condition to evaluate.
340
+ #
341
+ # ==== Raises
342
+ # ArgumentError:: condition not a Symbol or Proc.
343
+ #
344
+ # ==== Returns
345
+ # Boolean:: True if the condition is met.
346
+ #
347
+ # ==== Alternatives
348
+ # If condition is a symbol, it will be send'ed. If it is a Proc it will be
349
+ # called directly with self as an argument.
350
+ def _evaluate_condition(condition)
351
+ case condition
352
+ when Symbol : self.send(condition)
353
+ when Proc : condition.call(self)
354
+ else
355
+ raise ArgumentError,
356
+ 'Filter condtions need to be either a Symbol or a Proc'
357
+ end
358
+ end
359
+
360
+ # ==== Parameters
361
+ # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
362
+ # opts<Hash>::
363
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
364
+ # &block:: A block to use as a filter if filter is nil.
365
+ #
366
+ # ==== Notes
367
+ # If the filter already exists, its options will be replaced with opts.
368
+ def self.after(filter = nil, opts = {}, &block)
369
+ add_filter(self._after_filters, filter || block, opts)
370
+ end
371
+
372
+ # ==== Parameters
373
+ # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
374
+ # opts<Hash>::
375
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
376
+ # &block:: A block to use as a filter if filter is nil.
377
+ #
378
+ # ==== Notes
379
+ # If the filter already exists, its options will be replaced with opts.
380
+ def self.before(filter = nil, opts = {}, &block)
381
+ add_filter(self._before_filters, filter || block, opts)
382
+ end
383
+
384
+ # Skip an after filter that has been previously defined (perhaps in a
385
+ # superclass)
386
+ #
387
+ # ==== Parameters
388
+ # filter<Symbol>:: A filter name to skip.
389
+ def self.skip_after(filter)
390
+ skip_filter(self._after_filters, filter)
391
+ end
392
+
393
+ # Skip a before filter that has been previously defined (perhaps in a
394
+ # superclass).
395
+ #
396
+ # ==== Parameters
397
+ # filter<Symbol>:: A filter name to skip.
398
+ def self.skip_before(filter)
399
+ skip_filter(self._before_filters , filter)
400
+ end
401
+
402
+ #---
403
+ # Defaults that can be overridden by plugins, other mixins, or subclasses
404
+ def _filters_halted() "<html><body><h1>Filter Chain Halted!</h1></body></html>" end
405
+
406
+ # Method stub for setting up the session. This will be overriden by session
407
+ # modules.
408
+ def setup_session() end
409
+
410
+ # Method stub for finalizing up the session. This will be overriden by
411
+ # session modules.
412
+ def finalize_session() end
413
+
414
+ # Stub so content-type support in RenderMixin doesn't throw errors
415
+ attr_accessor :content_type
416
+
417
+ # Handles the template cache (which is used by BootLoader to cache the list
418
+ # of all templates).
419
+ #
420
+ # ==== Parameters
421
+ # template<String>::
422
+ # The full path to a template to add to the list of available templates
423
+ def self.add_path_to_template_cache(template)
424
+ return false if template.blank? || template.split("/").last.split(".").size != 3
425
+ key = template.match(/(.*)\.(.*)$/)[1]
426
+ self._template_path_cache[key] = template
427
+ end
428
+
429
+ # Resets the template_path_cache to an empty hash
430
+ def self.reset_template_path_cache!
431
+ self._template_path_cache = {}
432
+ end
433
+
434
+ # ==== Parameters
435
+ # name<~to_sym, Hash>:: The name of the URL to generate.
436
+ # rparams<Hash>:: Parameters for the route generation.
437
+ #
438
+ # ==== Returns
439
+ # String:: The generated URL.
440
+ #
441
+ # ==== Alternatives
442
+ # If a hash is used as the first argument, a default route will be
443
+ # generated based on it and rparams.
444
+ def url(name, rparams = {}, qparams = {})
445
+ unless rparams.is_a?(Hash) || qparams.empty?
446
+ rparams = qparams.merge(:id => rparams)
447
+ end
448
+ uri = Merb::Router.generate(name, rparams,
449
+ { :controller => controller_name,
450
+ :action => action_name,
451
+ :format => params[:format]
452
+ }
453
+ )
454
+ uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
455
+ uri
456
+ end
457
+ alias_method :relative_url, :url
458
+
459
+ # ==== Parameters
460
+ # name<~to_sym, Hash>:: The name of the URL to generate.
461
+ # rparams<Hash>:: Parameters for the route generation.
462
+ #
463
+ # ==== Returns
464
+ # String:: The generated url with protocol + hostname + URL.
465
+ #
466
+ # ==== Alternatives
467
+ # If a hash is used as the first argument, a default route will be
468
+ # generated based on it and rparams.
469
+ def absolute_url(name, rparams={})
470
+ request.protocol + request.host + url(name, rparams)
471
+ end
472
+
473
+ # Calls the capture method for the selected template engine.
474
+ #
475
+ # ==== Parameters
476
+ # *args:: Arguments to pass to the block.
477
+ # &block:: The template block to call.
478
+ #
479
+ # ==== Returns
480
+ # String:: The output of the block.
481
+ def capture(*args, &block)
482
+ send("capture_#{@_engine}", *args, &block)
483
+ end
484
+
485
+ # Calls the concatenate method for the selected template engine.
486
+ #
487
+ # ==== Parameters
488
+ # str<String>:: The string to concatenate to the buffer.
489
+ # binding<Binding>:: The binding to use for the buffer.
490
+ def concat(str, binding)
491
+ send("concat_#{@_engine}", str, binding)
492
+ end
493
+
494
+ private
495
+ # ==== Parameters
496
+ # filters<Array[Filter]>:: The filter list that this should be added to.
497
+ # filter<Filter>:: A filter that should be added.
498
+ # opts<Hash>::
499
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
500
+ #
501
+ # ==== Raises
502
+ # ArgumentError::
503
+ # Both :only and :exclude, or :if and :unless given, if filter is not a
504
+ # Symbol, String or Proc, or if an unknown option is passed.
505
+ def self.add_filter(filters, filter, opts={})
506
+ raise(ArgumentError,
507
+ "You can specify either :only or :exclude but
508
+ not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
509
+
510
+ raise(ArgumentError,
511
+ "You can specify either :if or :unless but
512
+ not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
513
+
514
+ opts.each_key do |key| raise(ArgumentError,
515
+ "You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
516
+ end
517
+
518
+ opts = normalize_filters!(opts)
519
+
520
+ case filter
521
+ when Symbol, Proc, String
522
+ if existing_filter = filters.find {|f| f.first.to_s[filter.to_s]}
523
+ existing_filter.last.replace(opts)
524
+ else
525
+ filters << [filter, opts]
526
+ end
527
+ else
528
+ raise(ArgumentError,
529
+ 'Filters need to be either a Symbol, String or a Proc'
530
+ )
531
+ end
532
+ end
533
+
534
+ # Skip a filter that was previously added to the filter chain. Useful in
535
+ # inheritence hierarchies.
536
+ #
537
+ # ==== Parameters
538
+ # filters<Array[Filter]>:: The filter list that this should be removed from.
539
+ # filter<Filter>:: A filter that should be removed.
540
+ #
541
+ # ==== Raises
542
+ # ArgumentError:: filter not Symbol or String.
543
+ def self.skip_filter(filters, filter)
544
+ raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
545
+ [Symbol, String].include? filter.class
546
+
547
+ Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
548
+ filters.reject! {|f| f.first.to_s[filter.to_s] }
549
+ end
550
+
551
+ # Ensures that the passed in hash values are always arrays.
552
+ #
553
+ # ==== Parameters
554
+ # opts<Hash>:: Options for the filters (see below).
555
+ #
556
+ # ==== Options (opts)
557
+ # :only<Symbol, Array[Symbol]>:: A list of actions.
558
+ # :exclude<Symbol, Array[Symbol]>:: A list of actions.
559
+ #
560
+ # ==== Examples
561
+ # normalize_filters!(:only => :new) #=> {:only => [:new]}
562
+ def self.normalize_filters!(opts={})
563
+ opts[:only] = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
564
+ opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
565
+ return opts
566
+ end
567
+
568
+ # Attempts to return the partial local variable corresponding to sym.
569
+ #
570
+ # ==== Paramteres
571
+ # sym<Symbol>:: Method name.
572
+ # *arg:: Arguments to pass to the method.
573
+ # &blk:: A block to pass to the method.
574
+ def method_missing(sym, *args, &blk)
575
+ return @_merb_partial_locals[sym] if @_merb_partial_locals && @_merb_partial_locals.key?(sym)
576
+ super
577
+ end
578
+ end