thorero 0.9.4.4 → 0.9.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. data/LICENSE +1 -1
  2. data/README +21 -0
  3. data/Rakefile +275 -108
  4. data/TODO +0 -0
  5. data/bin/merb +12 -0
  6. data/bin/merb-specs +5 -0
  7. data/docs/bootloading.dox +58 -0
  8. data/docs/documentation_standards +40 -0
  9. data/docs/merb-core-call-stack-diagram.mmap +0 -0
  10. data/docs/merb-core-call-stack-diagram.pdf +0 -0
  11. data/docs/merb-core-call-stack-diagram.png +0 -0
  12. data/docs/new_render_api +51 -0
  13. data/lib/merb-core.rb +603 -0
  14. data/lib/merb-core/autoload.rb +32 -0
  15. data/lib/merb-core/bootloader.rb +708 -0
  16. data/lib/merb-core/config.rb +303 -0
  17. data/lib/merb-core/constants.rb +43 -0
  18. data/lib/merb-core/controller/abstract_controller.rb +578 -0
  19. data/lib/merb-core/controller/exceptions.rb +302 -0
  20. data/lib/merb-core/controller/merb_controller.rb +256 -0
  21. data/lib/merb-core/controller/mime.rb +106 -0
  22. data/lib/merb-core/controller/mixins/authentication.rb +87 -0
  23. data/lib/merb-core/controller/mixins/controller.rb +290 -0
  24. data/lib/merb-core/controller/mixins/render.rb +481 -0
  25. data/lib/merb-core/controller/mixins/responder.rb +472 -0
  26. data/lib/merb-core/controller/template.rb +254 -0
  27. data/lib/merb-core/core_ext.rb +8 -0
  28. data/lib/merb-core/core_ext/kernel.rb +319 -0
  29. data/lib/merb-core/dispatch/cookies.rb +91 -0
  30. data/lib/merb-core/dispatch/dispatcher.rb +278 -0
  31. data/lib/merb-core/dispatch/exceptions.html.erb +303 -0
  32. data/lib/merb-core/dispatch/request.rb +603 -0
  33. data/lib/merb-core/dispatch/router.rb +179 -0
  34. data/lib/merb-core/dispatch/router/behavior.rb +867 -0
  35. data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
  36. data/lib/merb-core/dispatch/router/route.rb +321 -0
  37. data/lib/merb-core/dispatch/session.rb +78 -0
  38. data/lib/merb-core/dispatch/session/cookie.rb +168 -0
  39. data/lib/merb-core/dispatch/session/memcached.rb +184 -0
  40. data/lib/merb-core/dispatch/session/memory.rb +241 -0
  41. data/lib/merb-core/dispatch/worker.rb +28 -0
  42. data/lib/merb-core/gem_ext/erubis.rb +77 -0
  43. data/lib/{extlib → merb-core}/logger.rb +2 -2
  44. data/lib/merb-core/plugins.rb +59 -0
  45. data/lib/merb-core/rack.rb +21 -0
  46. data/lib/merb-core/rack/adapter.rb +44 -0
  47. data/lib/merb-core/rack/adapter/ebb.rb +25 -0
  48. data/lib/merb-core/rack/adapter/evented_mongrel.rb +26 -0
  49. data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
  50. data/lib/merb-core/rack/adapter/irb.rb +118 -0
  51. data/lib/merb-core/rack/adapter/mongrel.rb +26 -0
  52. data/lib/merb-core/rack/adapter/runner.rb +28 -0
  53. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
  54. data/lib/merb-core/rack/adapter/thin.rb +39 -0
  55. data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
  56. data/lib/merb-core/rack/adapter/webrick.rb +36 -0
  57. data/lib/merb-core/rack/application.rb +18 -0
  58. data/lib/merb-core/rack/handler/mongrel.rb +97 -0
  59. data/lib/merb-core/rack/middleware.rb +26 -0
  60. data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
  61. data/lib/merb-core/rack/middleware/profiler.rb +19 -0
  62. data/lib/merb-core/rack/middleware/static.rb +45 -0
  63. data/lib/merb-core/server.rb +252 -0
  64. data/lib/merb-core/tasks/audit.rake +68 -0
  65. data/lib/merb-core/tasks/merb.rb +1 -0
  66. data/lib/merb-core/tasks/merb_rake_helper.rb +12 -0
  67. data/lib/merb-core/test.rb +11 -0
  68. data/lib/merb-core/test/helpers.rb +9 -0
  69. data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
  70. data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
  71. data/lib/merb-core/test/helpers/request_helper.rb +344 -0
  72. data/lib/merb-core/test/helpers/route_helper.rb +33 -0
  73. data/lib/merb-core/test/helpers/view_helper.rb +121 -0
  74. data/lib/merb-core/test/matchers.rb +9 -0
  75. data/lib/merb-core/test/matchers/controller_matchers.rb +319 -0
  76. data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
  77. data/lib/merb-core/test/matchers/view_matchers.rb +335 -0
  78. data/lib/merb-core/test/run_specs.rb +47 -0
  79. data/lib/merb-core/test/tasks/spectasks.rb +68 -0
  80. data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
  81. data/lib/merb-core/test/test_ext/object.rb +14 -0
  82. data/lib/merb-core/test/test_ext/string.rb +14 -0
  83. data/lib/merb-core/vendor/facets.rb +2 -0
  84. data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
  85. data/lib/merb-core/vendor/facets/inflect.rb +345 -0
  86. data/lib/merb-core/version.rb +11 -0
  87. data/spec/private/config/adapter_spec.rb +32 -0
  88. data/spec/private/config/config_spec.rb +202 -0
  89. data/spec/private/config/environment_spec.rb +13 -0
  90. data/spec/private/config/spec_helper.rb +1 -0
  91. data/spec/private/core_ext/kernel_spec.rb +169 -0
  92. data/spec/private/dispatch/bootloader_spec.rb +24 -0
  93. data/spec/private/dispatch/cookies_spec.rb +107 -0
  94. data/spec/private/dispatch/dispatch_spec.rb +35 -0
  95. data/spec/private/dispatch/fixture/app/controllers/application.rb +4 -0
  96. data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +27 -0
  97. data/spec/private/dispatch/fixture/app/controllers/foo.rb +21 -0
  98. data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +8 -0
  99. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +37 -0
  100. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
  101. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
  102. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +40 -0
  103. data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
  104. data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +11 -0
  105. data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
  106. data/spec/private/dispatch/fixture/config/environments/development.rb +6 -0
  107. data/spec/private/dispatch/fixture/config/environments/production.rb +5 -0
  108. data/spec/private/dispatch/fixture/config/environments/test.rb +6 -0
  109. data/spec/private/dispatch/fixture/config/init.rb +45 -0
  110. data/spec/private/dispatch/fixture/config/rack.rb +11 -0
  111. data/spec/private/dispatch/fixture/config/router.rb +35 -0
  112. data/spec/private/dispatch/fixture/log/merb_test.log +1874 -0
  113. data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
  114. data/spec/private/dispatch/fixture/public/merb.fcgi +4 -0
  115. data/spec/private/dispatch/fixture/public/stylesheets/master.css +119 -0
  116. data/spec/private/dispatch/route_params_spec.rb +24 -0
  117. data/spec/private/dispatch/session_mixin_spec.rb +47 -0
  118. data/spec/private/dispatch/spec_helper.rb +1 -0
  119. data/spec/private/plugins/plugin_spec.rb +166 -0
  120. data/spec/private/rack/application_spec.rb +49 -0
  121. data/spec/private/router/behavior_spec.rb +60 -0
  122. data/spec/private/router/fixture/log/merb_test.log +139 -0
  123. data/spec/private/router/route_spec.rb +414 -0
  124. data/spec/private/router/router_spec.rb +175 -0
  125. data/spec/private/vendor/facets/plural_spec.rb +564 -0
  126. data/spec/private/vendor/facets/singular_spec.rb +489 -0
  127. data/spec/public/DEFINITIONS +11 -0
  128. data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +1 -0
  129. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +1 -0
  130. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +1 -0
  131. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +1 -0
  132. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +1 -0
  133. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  134. data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +1 -0
  135. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +1 -0
  136. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +1 -0
  137. data/spec/public/abstract_controller/controllers/cousins.rb +41 -0
  138. data/spec/public/abstract_controller/controllers/display.rb +54 -0
  139. data/spec/public/abstract_controller/controllers/filters.rb +193 -0
  140. data/spec/public/abstract_controller/controllers/helpers.rb +41 -0
  141. data/spec/public/abstract_controller/controllers/partial.rb +121 -0
  142. data/spec/public/abstract_controller/controllers/render.rb +113 -0
  143. data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +1 -0
  144. data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +1 -0
  145. data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +1 -0
  146. data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +1 -0
  147. data/spec/public/abstract_controller/controllers/views/layout/alt.erb +1 -0
  148. data/spec/public/abstract_controller/controllers/views/layout/custom.erb +1 -0
  149. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +1 -0
  150. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +1 -0
  151. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +1 -0
  152. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
  153. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +1 -0
  154. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  155. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +1 -0
  156. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +1 -0
  157. data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +1 -0
  158. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +1 -0
  159. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +1 -0
  160. data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +1 -0
  161. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +1 -0
  162. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +1 -0
  163. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +1 -0
  164. data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +1 -0
  165. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +1 -0
  166. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +1 -0
  167. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +1 -0
  168. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +1 -0
  169. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +1 -0
  170. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +1 -0
  171. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +1 -0
  172. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +1 -0
  173. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +1 -0
  174. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +1 -0
  175. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +1 -0
  176. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +1 -0
  177. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +1 -0
  178. data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +1 -0
  179. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +1 -0
  180. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +1 -0
  181. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +1 -0
  182. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +1 -0
  183. data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +1 -0
  184. data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +1 -0
  185. data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +1 -0
  186. data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
  187. data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +1 -0
  188. data/spec/public/abstract_controller/display_spec.rb +33 -0
  189. data/spec/public/abstract_controller/filter_spec.rb +106 -0
  190. data/spec/public/abstract_controller/helper_spec.rb +21 -0
  191. data/spec/public/abstract_controller/partial_spec.rb +61 -0
  192. data/spec/public/abstract_controller/render_spec.rb +90 -0
  193. data/spec/public/abstract_controller/spec_helper.rb +31 -0
  194. data/spec/public/boot_loader/boot_loader_spec.rb +33 -0
  195. data/spec/public/boot_loader/spec_helper.rb +1 -0
  196. data/spec/public/controller/authentication_spec.rb +103 -0
  197. data/spec/public/controller/base_spec.rb +36 -0
  198. data/spec/public/controller/controllers/authentication.rb +45 -0
  199. data/spec/public/controller/controllers/base.rb +36 -0
  200. data/spec/public/controller/controllers/display.rb +118 -0
  201. data/spec/public/controller/controllers/redirect.rb +30 -0
  202. data/spec/public/controller/controllers/responder.rb +93 -0
  203. data/spec/public/controller/controllers/url.rb +7 -0
  204. data/spec/public/controller/controllers/views/layout/custom.html.erb +1 -0
  205. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
  206. data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +1 -0
  207. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +1 -0
  208. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +1 -0
  209. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +1 -0
  210. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +1 -0
  211. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +1 -0
  212. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +1 -0
  213. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
  214. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +1 -0
  215. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +1 -0
  216. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +1 -0
  217. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +1 -0
  218. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +1 -0
  219. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +1 -0
  220. data/spec/public/controller/display_spec.rb +84 -0
  221. data/spec/public/controller/redirect_spec.rb +27 -0
  222. data/spec/public/controller/responder_spec.rb +163 -0
  223. data/spec/public/controller/spec_helper.rb +11 -0
  224. data/spec/public/controller/url_spec.rb +180 -0
  225. data/spec/public/core/merb_core_spec.rb +45 -0
  226. data/spec/public/core_ext/class_spec.rb +91 -0
  227. data/spec/public/core_ext/fixtures/core_ext_dependency.rb +2 -0
  228. data/spec/public/core_ext/kernel_spec.rb +9 -0
  229. data/spec/public/core_ext/spec_helper.rb +1 -0
  230. data/spec/public/directory_structure/directory/app/controllers/application.rb +3 -0
  231. data/spec/public/directory_structure/directory/app/controllers/base.rb +13 -0
  232. data/spec/public/directory_structure/directory/app/controllers/custom.rb +19 -0
  233. data/spec/public/directory_structure/directory/app/views/base/template.html.erb +1 -0
  234. data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +1 -0
  235. data/spec/public/directory_structure/directory/config/router.rb +3 -0
  236. data/spec/public/directory_structure/directory/log/merb_test.log +562 -0
  237. data/spec/public/directory_structure/directory_spec.rb +44 -0
  238. data/spec/public/logger/logger_spec.rb +181 -0
  239. data/spec/public/logger/spec_helper.rb +1 -0
  240. data/spec/public/reloading/directory/app/controllers/application.rb +3 -0
  241. data/spec/public/reloading/directory/app/controllers/reload.rb +6 -0
  242. data/spec/public/reloading/directory/config/init.rb +2 -0
  243. data/spec/public/reloading/directory/log/merb_test.log +138 -0
  244. data/spec/public/reloading/reload_spec.rb +103 -0
  245. data/spec/public/request/multipart_spec.rb +41 -0
  246. data/spec/public/request/request_spec.rb +228 -0
  247. data/spec/public/router/default_spec.rb +21 -0
  248. data/spec/public/router/deferred_spec.rb +22 -0
  249. data/spec/public/router/fixation_spec.rb +27 -0
  250. data/spec/public/router/fixture/log/merb_test.log +1556 -0
  251. data/spec/public/router/namespace_spec.rb +113 -0
  252. data/spec/public/router/nested_matches_spec.rb +97 -0
  253. data/spec/public/router/nested_resources_spec.rb +41 -0
  254. data/spec/public/router/resource_spec.rb +37 -0
  255. data/spec/public/router/resources_spec.rb +82 -0
  256. data/spec/public/router/spec_helper.rb +90 -0
  257. data/spec/public/router/special_spec.rb +61 -0
  258. data/spec/public/router/string_spec.rb +61 -0
  259. data/spec/public/template/template_spec.rb +104 -0
  260. data/spec/public/template/templates/error.html.erb +2 -0
  261. data/spec/public/template/templates/template.html.erb +1 -0
  262. data/spec/public/template/templates/template.html.myt +1 -0
  263. data/spec/public/test/controller_matchers_spec.rb +402 -0
  264. data/spec/public/test/controllers/controller_assertion_mock.rb +7 -0
  265. data/spec/public/test/controllers/dispatch_controller.rb +11 -0
  266. data/spec/public/test/controllers/spec_helper_controller.rb +38 -0
  267. data/spec/public/test/multipart_request_helper_spec.rb +159 -0
  268. data/spec/public/test/multipart_upload_text_file.txt +1 -0
  269. data/spec/public/test/request_helper_spec.rb +221 -0
  270. data/spec/public/test/route_helper_spec.rb +71 -0
  271. data/spec/public/test/route_matchers_spec.rb +162 -0
  272. data/spec/public/test/view_helper_spec.rb +96 -0
  273. data/spec/public/test/view_matchers_spec.rb +183 -0
  274. data/spec/spec_helper.rb +68 -0
  275. metadata +493 -41
  276. data/README.txt +0 -3
  277. data/lib/extlib.rb +0 -32
  278. data/lib/extlib/assertions.rb +0 -8
  279. data/lib/extlib/blank.rb +0 -42
  280. data/lib/extlib/class.rb +0 -175
  281. data/lib/extlib/hash.rb +0 -410
  282. data/lib/extlib/hook.rb +0 -366
  283. data/lib/extlib/inflection.rb +0 -141
  284. data/lib/extlib/lazy_array.rb +0 -106
  285. data/lib/extlib/mash.rb +0 -143
  286. data/lib/extlib/module.rb +0 -37
  287. data/lib/extlib/object.rb +0 -165
  288. data/lib/extlib/object_space.rb +0 -13
  289. data/lib/extlib/pathname.rb +0 -5
  290. data/lib/extlib/pooling.rb +0 -233
  291. data/lib/extlib/rubygems.rb +0 -38
  292. data/lib/extlib/simple_set.rb +0 -39
  293. data/lib/extlib/string.rb +0 -132
  294. data/lib/extlib/struct.rb +0 -8
  295. data/lib/extlib/tasks/release.rb +0 -9
  296. data/lib/extlib/time.rb +0 -12
  297. data/lib/extlib/version.rb +0 -3
  298. data/lib/extlib/virtual_file.rb +0 -10
@@ -0,0 +1,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