merb-core 0.9.2

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 (246) hide show
  1. data/LICENSE +20 -0
  2. data/README +21 -0
  3. data/Rakefile +285 -0
  4. data/TODO +0 -0
  5. data/bin/merb +8 -0
  6. data/bin/merb-specs +5 -0
  7. data/docs/bootloading.dox +57 -0
  8. data/docs/documentation_standards +40 -0
  9. data/docs/new_render_api +51 -0
  10. data/lib/merb-core.rb +304 -0
  11. data/lib/merb-core/autoload.rb +29 -0
  12. data/lib/merb-core/bootloader.rb +601 -0
  13. data/lib/merb-core/config.rb +284 -0
  14. data/lib/merb-core/constants.rb +43 -0
  15. data/lib/merb-core/controller/abstract_controller.rb +531 -0
  16. data/lib/merb-core/controller/exceptions.rb +257 -0
  17. data/lib/merb-core/controller/merb_controller.rb +214 -0
  18. data/lib/merb-core/controller/mime.rb +88 -0
  19. data/lib/merb-core/controller/mixins/controller.rb +262 -0
  20. data/lib/merb-core/controller/mixins/render.rb +324 -0
  21. data/lib/merb-core/controller/mixins/responder.rb +464 -0
  22. data/lib/merb-core/controller/template.rb +205 -0
  23. data/lib/merb-core/core_ext.rb +12 -0
  24. data/lib/merb-core/core_ext/class.rb +192 -0
  25. data/lib/merb-core/core_ext/hash.rb +422 -0
  26. data/lib/merb-core/core_ext/kernel.rb +304 -0
  27. data/lib/merb-core/core_ext/mash.rb +154 -0
  28. data/lib/merb-core/core_ext/object.rb +136 -0
  29. data/lib/merb-core/core_ext/object_space.rb +14 -0
  30. data/lib/merb-core/core_ext/rubygems.rb +28 -0
  31. data/lib/merb-core/core_ext/set.rb +41 -0
  32. data/lib/merb-core/core_ext/string.rb +69 -0
  33. data/lib/merb-core/dispatch/cookies.rb +92 -0
  34. data/lib/merb-core/dispatch/dispatcher.rb +233 -0
  35. data/lib/merb-core/dispatch/exceptions.html.erb +297 -0
  36. data/lib/merb-core/dispatch/request.rb +560 -0
  37. data/lib/merb-core/dispatch/router.rb +141 -0
  38. data/lib/merb-core/dispatch/router/behavior.rb +777 -0
  39. data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
  40. data/lib/merb-core/dispatch/router/route.rb +212 -0
  41. data/lib/merb-core/dispatch/session.rb +28 -0
  42. data/lib/merb-core/dispatch/session/cookie.rb +166 -0
  43. data/lib/merb-core/dispatch/session/memcached.rb +161 -0
  44. data/lib/merb-core/dispatch/session/memory.rb +234 -0
  45. data/lib/merb-core/gem_ext/erubis.rb +19 -0
  46. data/lib/merb-core/logger.rb +230 -0
  47. data/lib/merb-core/plugins.rb +25 -0
  48. data/lib/merb-core/rack.rb +15 -0
  49. data/lib/merb-core/rack/adapter.rb +42 -0
  50. data/lib/merb-core/rack/adapter/ebb.rb +22 -0
  51. data/lib/merb-core/rack/adapter/evented_mongrel.rb +24 -0
  52. data/lib/merb-core/rack/adapter/fcgi.rb +16 -0
  53. data/lib/merb-core/rack/adapter/irb.rb +108 -0
  54. data/lib/merb-core/rack/adapter/mongrel.rb +25 -0
  55. data/lib/merb-core/rack/adapter/runner.rb +27 -0
  56. data/lib/merb-core/rack/adapter/thin.rb +27 -0
  57. data/lib/merb-core/rack/adapter/webrick.rb +35 -0
  58. data/lib/merb-core/rack/application.rb +77 -0
  59. data/lib/merb-core/rack/handler/mongrel.rb +97 -0
  60. data/lib/merb-core/server.rb +184 -0
  61. data/lib/merb-core/test.rb +10 -0
  62. data/lib/merb-core/test/helpers.rb +9 -0
  63. data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
  64. data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
  65. data/lib/merb-core/test/helpers/request_helper.rb +257 -0
  66. data/lib/merb-core/test/helpers/route_helper.rb +33 -0
  67. data/lib/merb-core/test/helpers/view_helper.rb +121 -0
  68. data/lib/merb-core/test/matchers.rb +9 -0
  69. data/lib/merb-core/test/matchers/controller_matchers.rb +269 -0
  70. data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
  71. data/lib/merb-core/test/matchers/view_matchers.rb +293 -0
  72. data/lib/merb-core/test/run_specs.rb +38 -0
  73. data/lib/merb-core/test/tasks/spectasks.rb +39 -0
  74. data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
  75. data/lib/merb-core/test/test_ext/object.rb +14 -0
  76. data/lib/merb-core/vendor/facets.rb +2 -0
  77. data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
  78. data/lib/merb-core/vendor/facets/inflect.rb +211 -0
  79. data/lib/merb-core/version.rb +11 -0
  80. data/spec/private/config/adapter_spec.rb +32 -0
  81. data/spec/private/config/config_spec.rb +139 -0
  82. data/spec/private/config/environment_spec.rb +13 -0
  83. data/spec/private/config/spec_helper.rb +1 -0
  84. data/spec/private/core_ext/hash_spec.rb +506 -0
  85. data/spec/private/core_ext/kernel_spec.rb +46 -0
  86. data/spec/private/core_ext/object_spec.rb +39 -0
  87. data/spec/private/core_ext/set_spec.rb +26 -0
  88. data/spec/private/core_ext/string_spec.rb +9 -0
  89. data/spec/private/dispatch/cookies_spec.rb +107 -0
  90. data/spec/private/dispatch/dispatch_spec.rb +26 -0
  91. data/spec/private/dispatch/fixture/app/controllers/application.rb +4 -0
  92. data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +27 -0
  93. data/spec/private/dispatch/fixture/app/controllers/foo.rb +21 -0
  94. data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +8 -0
  95. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +37 -0
  96. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
  97. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
  98. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +40 -0
  99. data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
  100. data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +11 -0
  101. data/spec/private/dispatch/fixture/config/environments/development.rb +6 -0
  102. data/spec/private/dispatch/fixture/config/environments/production.rb +5 -0
  103. data/spec/private/dispatch/fixture/config/environments/test.rb +6 -0
  104. data/spec/private/dispatch/fixture/config/init.rb +45 -0
  105. data/spec/private/dispatch/fixture/config/rack.rb +1 -0
  106. data/spec/private/dispatch/fixture/config/router.rb +35 -0
  107. data/spec/private/dispatch/fixture/log/development.log +1 -0
  108. data/spec/private/dispatch/fixture/log/merb.4000.pid +1 -0
  109. data/spec/private/dispatch/fixture/log/merb_test.log +2040 -0
  110. data/spec/private/dispatch/fixture/log/production.log +1 -0
  111. data/spec/private/dispatch/fixture/merb.4000.pid +1 -0
  112. data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
  113. data/spec/private/dispatch/fixture/public/merb.fcgi +4 -0
  114. data/spec/private/dispatch/fixture/public/stylesheets/master.css +119 -0
  115. data/spec/private/dispatch/route_params_spec.rb +24 -0
  116. data/spec/private/dispatch/spec_helper.rb +1 -0
  117. data/spec/private/plugins/plugin_spec.rb +81 -0
  118. data/spec/private/rack/application_spec.rb +43 -0
  119. data/spec/public/DEFINITIONS +11 -0
  120. data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +1 -0
  121. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +1 -0
  122. data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +1 -0
  123. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +1 -0
  124. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +1 -0
  125. data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  126. data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +1 -0
  127. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +1 -0
  128. data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +1 -0
  129. data/spec/public/abstract_controller/controllers/display.rb +54 -0
  130. data/spec/public/abstract_controller/controllers/filters.rb +167 -0
  131. data/spec/public/abstract_controller/controllers/helpers.rb +31 -0
  132. data/spec/public/abstract_controller/controllers/partial.rb +106 -0
  133. data/spec/public/abstract_controller/controllers/render.rb +86 -0
  134. data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +1 -0
  135. data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +1 -0
  136. data/spec/public/abstract_controller/controllers/views/layout/alt.erb +1 -0
  137. data/spec/public/abstract_controller/controllers/views/layout/custom.erb +1 -0
  138. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +1 -0
  139. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +1 -0
  140. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +1 -0
  141. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
  142. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +1 -0
  143. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
  144. data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +1 -0
  145. data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +1 -0
  146. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +1 -0
  147. data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +1 -0
  148. data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +1 -0
  149. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +1 -0
  150. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +1 -0
  151. data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +1 -0
  152. data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +1 -0
  153. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +1 -0
  154. data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +1 -0
  155. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +1 -0
  156. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +1 -0
  157. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +1 -0
  158. data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +1 -0
  159. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +1 -0
  160. data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +1 -0
  161. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +1 -0
  162. data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +1 -0
  163. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +1 -0
  164. data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +1 -0
  165. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +1 -0
  166. data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +1 -0
  167. data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +1 -0
  168. data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +1 -0
  169. data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +1 -0
  170. data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
  171. data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +1 -0
  172. data/spec/public/abstract_controller/display_spec.rb +33 -0
  173. data/spec/public/abstract_controller/filter_spec.rb +80 -0
  174. data/spec/public/abstract_controller/helper_spec.rb +13 -0
  175. data/spec/public/abstract_controller/partial_spec.rb +53 -0
  176. data/spec/public/abstract_controller/render_spec.rb +70 -0
  177. data/spec/public/abstract_controller/spec_helper.rb +27 -0
  178. data/spec/public/boot_loader/boot_loader_spec.rb +33 -0
  179. data/spec/public/boot_loader/spec_helper.rb +1 -0
  180. data/spec/public/controller/base_spec.rb +31 -0
  181. data/spec/public/controller/controllers/base.rb +41 -0
  182. data/spec/public/controller/controllers/display.rb +40 -0
  183. data/spec/public/controller/controllers/responder.rb +67 -0
  184. data/spec/public/controller/controllers/url.rb +7 -0
  185. data/spec/public/controller/controllers/views/layout/custom.html.erb +1 -0
  186. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +1 -0
  187. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +1 -0
  188. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +1 -0
  189. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +1 -0
  190. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +1 -0
  191. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +1 -0
  192. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +1 -0
  193. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +1 -0
  194. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +1 -0
  195. data/spec/public/controller/display_spec.rb +34 -0
  196. data/spec/public/controller/log/merb.4000.pid +1 -0
  197. data/spec/public/controller/responder_spec.rb +95 -0
  198. data/spec/public/controller/spec_helper.rb +9 -0
  199. data/spec/public/controller/url_spec.rb +152 -0
  200. data/spec/public/directory_structure/directory/app/controllers/application.rb +3 -0
  201. data/spec/public/directory_structure/directory/app/controllers/base.rb +13 -0
  202. data/spec/public/directory_structure/directory/app/controllers/custom.rb +19 -0
  203. data/spec/public/directory_structure/directory/app/views/base/template.html.erb +1 -0
  204. data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +1 -0
  205. data/spec/public/directory_structure/directory/config/router.rb +3 -0
  206. data/spec/public/directory_structure/directory/log/merb.4000.pid +1 -0
  207. data/spec/public/directory_structure/directory/log/merb_test.log +265 -0
  208. data/spec/public/directory_structure/directory/merb.4000.pid +1 -0
  209. data/spec/public/directory_structure/directory_spec.rb +44 -0
  210. data/spec/public/logger/logger_spec.rb +175 -0
  211. data/spec/public/logger/spec_helper.rb +1 -0
  212. data/spec/public/reloading/directory/app/controllers/application.rb +3 -0
  213. data/spec/public/reloading/directory/app/controllers/reload.rb +6 -0
  214. data/spec/public/reloading/directory/config/init.rb +2 -0
  215. data/spec/public/reloading/directory/log/merb.4000.pid +1 -0
  216. data/spec/public/reloading/directory/log/merb_test.log +59 -0
  217. data/spec/public/reloading/directory/merb.4000.pid +1 -0
  218. data/spec/public/reloading/reload_spec.rb +80 -0
  219. data/spec/public/request/multipart_spec.rb +15 -0
  220. data/spec/public/request/request_spec.rb +207 -0
  221. data/spec/public/router/default_spec.rb +21 -0
  222. data/spec/public/router/deferred_spec.rb +22 -0
  223. data/spec/public/router/namespace_spec.rb +113 -0
  224. data/spec/public/router/nested_resources_spec.rb +34 -0
  225. data/spec/public/router/resource_spec.rb +45 -0
  226. data/spec/public/router/resources_spec.rb +57 -0
  227. data/spec/public/router/spec_helper.rb +72 -0
  228. data/spec/public/router/special_spec.rb +44 -0
  229. data/spec/public/router/string_spec.rb +61 -0
  230. data/spec/public/template/template_spec.rb +92 -0
  231. data/spec/public/template/templates/error.html.erb +2 -0
  232. data/spec/public/template/templates/template.html.erb +1 -0
  233. data/spec/public/template/templates/template.html.myt +1 -0
  234. data/spec/public/test/controller_matchers_spec.rb +378 -0
  235. data/spec/public/test/controllers/controller_assertion_mock.rb +7 -0
  236. data/spec/public/test/controllers/dispatch_controller.rb +11 -0
  237. data/spec/public/test/controllers/spec_helper_controller.rb +30 -0
  238. data/spec/public/test/multipart_request_helper_spec.rb +159 -0
  239. data/spec/public/test/multipart_upload_text_file.txt +1 -0
  240. data/spec/public/test/request_helper_spec.rb +153 -0
  241. data/spec/public/test/route_helper_spec.rb +54 -0
  242. data/spec/public/test/route_matchers_spec.rb +133 -0
  243. data/spec/public/test/view_helper_spec.rb +96 -0
  244. data/spec/public/test/view_matchers_spec.rb +107 -0
  245. data/spec/spec_helper.rb +71 -0
  246. metadata +488 -0
@@ -0,0 +1,304 @@
1
+ module Kernel
2
+ # Loads the given string as a gem. Execution is deferred to
3
+ # the Merb::BootLoader::Dependencies.run during bootup.
4
+ #
5
+ # ==== Parameters
6
+ # name<String>:: The name of the gem to load.
7
+ # *ver<Gem::Requirement, Gem::Version, Array, ~to_str>::
8
+ # Version requirements to be passed to Gem.activate.
9
+ def dependency(name, *ver)
10
+ Merb::BootLoader::Dependencies.dependencies << [name, ver]
11
+ end
12
+
13
+ # Loads the given string as a gem.
14
+ #
15
+ # ==== Parameters
16
+ # name<String>:: The name of the gem to load.
17
+ # *ver<Gem::Requirement, Gem::Version, Array, ~to_str>::
18
+ # Version requirements to be passed to Gem.activate.
19
+ #
20
+ # ==== Notes
21
+ # If the gem cannot be found, the method will attempt to require the string
22
+ # as a library.
23
+ #
24
+ # This new version tries to load the file via ROOT/gems first before moving
25
+ # off to the system gems (so if you have a lower version of a gem in
26
+ # ROOT/gems, it'll still get loaded).
27
+ def load_dependency(name, *ver)
28
+ try_framework = Merb.frozen?
29
+ begin
30
+ # If this is a piece of merb, and we're frozen, try to require
31
+ # first, so we can pick it up from framework/,
32
+ # otherwise try activating the gem
33
+ if name =~ /^merb/ && try_framework
34
+ require name
35
+ else
36
+ gem(name, *ver) if ver
37
+ require name
38
+ Merb.logger.info!("loading gem '#{name}' from #{__app_file_trace__.first} ...")
39
+ end
40
+ rescue LoadError
41
+ if try_framework
42
+ try_framework = false
43
+ retry
44
+ else
45
+ Merb.logger.info!("loading gem '#{name}' from #{__app_file_trace__.first} ...")
46
+ # Failed requiring as a gem, let's try loading with a normal require.
47
+ require name
48
+ end
49
+ end
50
+ end
51
+
52
+ # Loads both gem and library dependencies that are passed in as arguments.
53
+ # Execution is deferred to the Merb::BootLoader::Dependencies.run during bootup.
54
+ #
55
+ # ==== Parameters
56
+ # *args<String, Hash, Array>:: The dependencies to load.
57
+ def dependencies(*args)
58
+ args.each do |arg|
59
+ case arg
60
+ when String then dependency(arg)
61
+ when Hash then arg.each { |r,v| dependency(r, v) }
62
+ when Array then arg.each { |r| dependency(r) }
63
+ end
64
+ end
65
+ end
66
+
67
+ # Loads both gem and library dependencies that are passed in as arguments.
68
+ #
69
+ # ==== Parameters
70
+ # *args<String, Hash, Array>:: The dependencies to load.
71
+ #
72
+ # ==== Notes
73
+ # Each argument can be:
74
+ # String:: Single dependency.
75
+ # Hash::
76
+ # Multiple dependencies where the keys are names and the values versions.
77
+ # Array:: Multiple string dependencies.
78
+ #
79
+ # ==== Examples
80
+ # dependencies "RedCloth" # Loads the the RedCloth gem
81
+ # dependencies "RedCloth", "merb_helpers" # Loads RedCloth and merb_helpers
82
+ # dependencies "RedCloth" => "3.0" # Loads RedCloth 3.0
83
+ def load_dependencies(*args)
84
+ args.each do |arg|
85
+ case arg
86
+ when String then load_dependency(arg)
87
+ when Hash then arg.each { |r,v| load_dependency(r, v) }
88
+ when Array then arg.each { |r| load_dependency(r) }
89
+ end
90
+ end
91
+ end
92
+
93
+ # Does a basic require, and prints a message if an error occurs.
94
+ #
95
+ # ==== Parameters
96
+ # library<~to_s>:: The library to attempt to include.
97
+ # message<String>:: The error to add to the log upon failure. Defaults to nil.
98
+ def rescue_require(library, message = nil)
99
+ require library
100
+ rescue LoadError, RuntimeError
101
+ Merb.logger.error!(message) if message
102
+ end
103
+
104
+ # Used in Merb.root/config/init.rb to tell Merb which ORM (Object Relational
105
+ # Mapper) you wish to use. Currently Merb has plugins to support
106
+ # ActiveRecord, DataMapper, and Sequel.
107
+ #
108
+ # ==== Parameters
109
+ # orm<~to_s>:: The ORM to use.
110
+ #
111
+ # ==== Examples
112
+ # # This line goes in dependencies.yml
113
+ # use_orm :datamapper
114
+ #
115
+ # # This will use the DataMapper generator for your ORM
116
+ # $ ruby script/generate model MyModel
117
+ def use_orm(orm)
118
+ if !Merb.generator_scope.include?(:merb_default) && !Merb.generator_scope.include?(orm.to_sym)
119
+ raise "Don't call use_orm more than once"
120
+ end
121
+ begin
122
+ Merb.generator_scope.delete(:merb_default)
123
+ orm_plugin = orm.to_s.match(/^merb_/) ? orm.to_s : "merb_#{orm}"
124
+ Merb.generator_scope.unshift(orm.to_sym) unless Merb.generator_scope.include?(orm.to_sym)
125
+ Kernel.dependency(orm_plugin)
126
+ rescue LoadError => e
127
+ Merb.logger.warn!("The #{orm_plugin} gem was not found. You may need to install it.")
128
+ raise e
129
+ end
130
+ end
131
+
132
+ # Used in Merb.root/config/init.rb to tell Merb which testing framework to
133
+ # use. Currently Merb has plugins to support RSpec and Test::Unit.
134
+ #
135
+ # ==== Parameters
136
+ # test_framework<Symbol>::
137
+ # The test framework to use. Currently only supports :rspec and :test_unit.
138
+ #
139
+ # ==== Examples
140
+ # # This line goes in dependencies.yml
141
+ # use_test :rspec
142
+ #
143
+ # # This will now use the RSpec generator for tests
144
+ # $ ruby script/generate controller MyController
145
+ def use_test(test_framework, *test_dependencies)
146
+ raise "use_test only supports :rspec and :test_unit currently" unless
147
+ [:rspec, :test_unit].include?(test_framework.to_sym)
148
+ Merb.generator_scope.delete(:rspec)
149
+ Merb.generator_scope.delete(:test_unit)
150
+ Merb.generator_scope.push(test_framework.to_sym)
151
+
152
+ dependencies test_dependencies if Merb.env == "test" || Merb.env.nil?
153
+ end
154
+
155
+ # ==== Returns
156
+ # Array[String]:: A stack trace of the applications files.
157
+ def __app_file_trace__
158
+ caller.select do |call|
159
+ call.include?(Merb.root) && !call.include?(Merb.root + "/framework")
160
+ end.map do |call|
161
+ file, line = call.scan(Regexp.new("#{Merb.root}/(.*):(.*)")).first
162
+ "#{file}:#{line}"
163
+ end
164
+ end
165
+
166
+ # ==== Parameters
167
+ # i<Fixnum>:: The caller number. Defaults to 1.
168
+ #
169
+ # ==== Returns
170
+ # Array[Array]:: The file, line and method of the caller.
171
+ #
172
+ # ==== Examples
173
+ # __caller_info__(1)
174
+ # # => ['/usr/lib/ruby/1.8/irb/workspace.rb', '52', 'irb_binding']
175
+ def __caller_info__(i = 1)
176
+ file, line, meth = caller[i].scan(/(.*?):(\d+):in `(.*?)'/).first
177
+ end
178
+
179
+ # ==== Parameters
180
+ # file<String>:: The file to read.
181
+ # line<Fixnum>:: The line number to look for.
182
+ # size<Fixnum>::
183
+ # Number of lines to include above and below the the line to look for.
184
+ # Defaults to 4.
185
+ #
186
+ # ==== Returns
187
+ # Array[Array]::
188
+ # Triplets containing the line number, the line and whether this was the
189
+ # searched line.
190
+ #
191
+ # ==== Examples
192
+ # __caller_lines__('/usr/lib/ruby/1.8/debug.rb', 122, 2) # =>
193
+ # [
194
+ # [ 120, " def check_suspend", false ],
195
+ # [ 121, " return if Thread.critical", false ],
196
+ # [ 122, " while (Thread.critical = true; @suspend_next)", true ],
197
+ # [ 123, " DEBUGGER__.waiting.push Thread.current", false ],
198
+ # [ 124, " @suspend_next = false", false ]
199
+ # ]
200
+ def __caller_lines__(file, line, size = 4)
201
+ return [['Template Error!', "problem while rendering", false]] if file =~ /\(erubis\)/
202
+ lines = File.readlines(file)
203
+ current = line.to_i - 1
204
+
205
+ first = current - size
206
+ first = first < 0 ? 0 : first
207
+
208
+ last = current + size
209
+ last = last > lines.size ? lines.size : last
210
+
211
+ log = lines[first..last]
212
+
213
+ area = []
214
+
215
+ log.each_with_index do |line, index|
216
+ index = index + first + 1
217
+ area << [index, line.chomp, index == current + 1]
218
+ end
219
+
220
+ area
221
+ end
222
+
223
+ # Takes a block, profiles the results of running the block 100 times and
224
+ # writes out the results in a file.
225
+ #
226
+ # ==== Parameters
227
+ # name<~to_s>::
228
+ # The file name. The result will be written out to
229
+ # Merb.root/"log/#{name}.html".
230
+ # min<Fixnum>::
231
+ # Minimum percentage of the total time a method must take for it to be
232
+ # included in the result. Defaults to 1.
233
+ #
234
+ # ==== Returns
235
+ # String:: The result of the profiling.
236
+ #
237
+ # ==== Notes
238
+ # Requires ruby-prof (<tt>sudo gem install ruby-prof</tt>)
239
+ #
240
+ # ==== Examples
241
+ # __profile__("MyProfile", 5, 30) do
242
+ # rand(10)**rand(10)
243
+ # puts "Profile run"
244
+ # end
245
+ #
246
+ # Assuming that the total time taken for #puts calls was less than 5% of the
247
+ # total time to run, #puts won't appear in the profile report.
248
+ # The code block will be run 30 times.
249
+ def __profile__(name, min=1, iter=100)
250
+ require 'ruby-prof' unless defined?(RubyProf)
251
+ return_result = ''
252
+ result = RubyProf.profile do
253
+ iter.times{return_result = yield}
254
+ end
255
+ printer = RubyProf::GraphHtmlPrinter.new(result)
256
+ path = File.join(Merb.root, 'log', "#{name}.html")
257
+ File.open(path, 'w') do |file|
258
+ printer.print(file, {:min_percent => min,
259
+ :print_file => true})
260
+ end
261
+ return_result
262
+ end
263
+
264
+ # Extracts an options hash if it is the last item in the args array. Used
265
+ # internally in methods that take *args.
266
+ #
267
+ # ==== Parameters
268
+ # args<Array>:: The arguments to extract the hash from.
269
+ #
270
+ # ==== Examples
271
+ # def render(*args,&blk)
272
+ # opts = extract_options_from_args!(args) || {}
273
+ # # [...]
274
+ # end
275
+ def extract_options_from_args!(args)
276
+ args.pop if Hash === args.last
277
+ end
278
+
279
+ # Checks that the given objects quack like the given conditions.
280
+ #
281
+ # ==== Parameters
282
+ # opts<Hash>::
283
+ # Conditions to enforce. Each key will receive a quacks_like? call with the
284
+ # value (see Object#quacks_like? for details).
285
+ #
286
+ # ==== Raises
287
+ # ArgumentError:: An object failed to quack like a condition.
288
+ def enforce!(opts = {})
289
+ opts.each do |k,v|
290
+ raise ArgumentError, "#{k.inspect} doesn't quack like #{v.inspect}" unless k.quacks_like?(v)
291
+ end
292
+ end
293
+
294
+ unless Kernel.respond_to?(:debugger)
295
+
296
+ # Define debugger method so that code even works if debugger was not
297
+ # requested. Drops a note to the logs that Debugger was not available.
298
+ def debugger
299
+ Merb.logger.info! "\n***** Debugger requested, but was not " +
300
+ "available: Start server with --debugger " +
301
+ "to enable *****\n"
302
+ end
303
+ end
304
+ end
@@ -0,0 +1,154 @@
1
+ # This class has dubious semantics and we only have it so that people can write
2
+ # params[:key] instead of params['key'].
3
+ class Mash < Hash
4
+
5
+ # ==== Parameters
6
+ # constructor<Object>::
7
+ # The default value for the mash. Defaults to an empty hash.
8
+ #
9
+ # ==== Alternatives
10
+ # If constructor is a Hash, a new mash will be created based on the keys of
11
+ # the hash and no default value will be set.
12
+ def initialize(constructor = {})
13
+ if constructor.is_a?(Hash)
14
+ super()
15
+ update(constructor)
16
+ else
17
+ super(constructor)
18
+ end
19
+ end
20
+
21
+ # ==== Parameters
22
+ # key<Object>:: The default value for the mash. Defaults to nil.
23
+ #
24
+ # ==== Alternatives
25
+ # If key is a Symbol and it is a key in the mash, then the default value will
26
+ # be set to the value matching the key.
27
+ def default(key = nil)
28
+ if key.is_a?(Symbol) && include?(key = key.to_s)
29
+ self[key]
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
36
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
37
+
38
+ # ==== Parameters
39
+ # key<Object>:: The key to set. This will be run through convert_key.
40
+ # value<Object>::
41
+ # The value to set the key to. This will be run through convert_value.
42
+ def []=(key, value)
43
+ regular_writer(convert_key(key), convert_value(value))
44
+ end
45
+
46
+ # ==== Parameters
47
+ # other_hash<Hash>::
48
+ # A hash to update values in the mash with. The keys and the values will be
49
+ # converted to Mash format.
50
+ #
51
+ # ==== Returns
52
+ # Mash:: The updated mash.
53
+ def update(other_hash)
54
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
55
+ self
56
+ end
57
+
58
+ alias_method :merge!, :update
59
+
60
+ # ==== Parameters
61
+ # key<Object>:: The key to check for. This will be run through convert_key.
62
+ #
63
+ # ==== Returns
64
+ # Boolean:: True if the key exists in the mash.
65
+ def key?(key)
66
+ super(convert_key(key))
67
+ end
68
+
69
+ # def include? def has_key? def member?
70
+ alias_method :include?, :key?
71
+ alias_method :has_key?, :key?
72
+ alias_method :member?, :key?
73
+
74
+ # ==== Parameters
75
+ # key<Object>:: The key to fetch. This willbe run through convert_key.
76
+ # extras:: Default value.
77
+ #
78
+ # ==== Returns
79
+ # Object:: The value at key or the default value.
80
+ def fetch(key, *extras)
81
+ super(convert_key(key), *extras)
82
+ end
83
+
84
+ # ==== Parameters
85
+ # indices<Array>::
86
+ # The keys to retrieve values for. These will be run through convert_key.
87
+ def values_at(*indices)
88
+ indices.collect {|key| self[convert_key(key)]}
89
+ end
90
+
91
+ # ==== Returns
92
+ # Mash:: A duplicate of this mash.
93
+ def dup
94
+ Mash.new(self)
95
+ end
96
+
97
+ # ==== Parameters
98
+ # hash<Hash>:: The hash to merge with the mash.
99
+ #
100
+ # ==== Returns
101
+ # Mash:: A new mash with the hash values merged in.
102
+ def merge(hash)
103
+ self.dup.update(hash)
104
+ end
105
+
106
+ # ==== Parameters
107
+ # key<Object>::
108
+ # The key to delete from the mash. This will be run through convert_key.
109
+ def delete(key)
110
+ super(convert_key(key))
111
+ end
112
+
113
+ # Used to provide the same interface as Hash.
114
+ #
115
+ # ==== Returns
116
+ # Mash:: This mash unchanged.
117
+ def stringify_keys!; self end
118
+
119
+ # ==== Returns
120
+ # Hash:: The mash as a Hash with string keys.
121
+ def to_hash
122
+ Hash.new(default).merge(self)
123
+ end
124
+
125
+ protected
126
+ # ==== Parameters
127
+ # key<Object>:: The key to convert.
128
+ #
129
+ # ==== Returns
130
+ # Object::
131
+ # The converted key. If the key was a symbol, it will be converted to a
132
+ # string.
133
+ def convert_key(key)
134
+ key.kind_of?(Symbol) ? key.to_s : key
135
+ end
136
+
137
+ # ==== Parameters
138
+ # value<Object>:: The value to convert.
139
+ #
140
+ # ==== Returns
141
+ # Object::
142
+ # The converted value. A Hash or an Array of hashes, will be converted to
143
+ # their Mash equivalents.
144
+ def convert_value(value)
145
+ case value
146
+ when Hash
147
+ value.to_mash
148
+ when Array
149
+ value.collect { |e| e.is_a?(Hash) ? e.to_mash : e }
150
+ else
151
+ value
152
+ end
153
+ end
154
+ end