merb 0.5.3 → 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 (294) hide show
  1. data/LICENSE +0 -20
  2. data/README +0 -277
  3. data/Rakefile +80 -199
  4. data/TODO +0 -3
  5. metadata +19 -438
  6. data/SVN_REVISION +0 -1
  7. data/app_generators/merb/USAGE +0 -5
  8. data/app_generators/merb/merb_generator.rb +0 -108
  9. data/app_generators/merb/templates/Rakefile +0 -124
  10. data/app_generators/merb/templates/app/controllers/application.rb +0 -3
  11. data/app_generators/merb/templates/app/controllers/exceptions.rb +0 -13
  12. data/app_generators/merb/templates/app/helpers/global_helper.rb +0 -5
  13. data/app_generators/merb/templates/app/mailers/views/layout/application.html.erb +0 -1
  14. data/app_generators/merb/templates/app/mailers/views/layout/application.text.erb +0 -1
  15. data/app_generators/merb/templates/app/parts/views/layout/application.html.erb +0 -1
  16. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +0 -216
  17. data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +0 -38
  18. data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +0 -40
  19. data/app_generators/merb/templates/app/views/layout/application.html.erb +0 -11
  20. data/app_generators/merb/templates/config/boot.rb +0 -11
  21. data/app_generators/merb/templates/config/dependencies.rb +0 -41
  22. data/app_generators/merb/templates/config/environments/development.rb +0 -1
  23. data/app_generators/merb/templates/config/environments/production.rb +0 -1
  24. data/app_generators/merb/templates/config/environments/test.rb +0 -1
  25. data/app_generators/merb/templates/config/merb.yml +0 -82
  26. data/app_generators/merb/templates/config/merb_init.rb +0 -17
  27. data/app_generators/merb/templates/config/plugins.yml +0 -1
  28. data/app_generators/merb/templates/config/router.rb +0 -35
  29. data/app_generators/merb/templates/config/upload.conf +0 -0
  30. data/app_generators/merb/templates/public/images/merb.jpg +0 -0
  31. data/app_generators/merb/templates/public/merb.fcgi +0 -6
  32. data/app_generators/merb/templates/public/stylesheets/master.css +0 -119
  33. data/app_generators/merb/templates/script/destroy +0 -32
  34. data/app_generators/merb/templates/script/generate +0 -32
  35. data/app_generators/merb/templates/script/stop_merb +0 -13
  36. data/app_generators/merb/templates/script/win_script.cmd +0 -1
  37. data/app_generators/merb/templates/spec/spec.opts +0 -6
  38. data/app_generators/merb/templates/spec/spec_helper.rb +0 -15
  39. data/app_generators/merb/templates/test/test_helper.rb +0 -14
  40. data/app_generators/merb_plugin/USAGE +0 -5
  41. data/app_generators/merb_plugin/merb_plugin_generator.rb +0 -68
  42. data/app_generators/merb_plugin/templates/LICENSE +0 -20
  43. data/app_generators/merb_plugin/templates/README +0 -4
  44. data/app_generators/merb_plugin/templates/Rakefile +0 -35
  45. data/app_generators/merb_plugin/templates/TODO +0 -5
  46. data/app_generators/merb_plugin/templates/merbtasks.rb +0 -6
  47. data/app_generators/merb_plugin/templates/sampleplugin.rb +0 -10
  48. data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +0 -7
  49. data/app_generators/merb_plugin/templates/spec_helper.rb +0 -2
  50. data/bin/merb +0 -4
  51. data/lib/autotest/discover.rb +0 -3
  52. data/lib/autotest/merb_rspec.rb +0 -80
  53. data/lib/merb.rb +0 -188
  54. data/lib/merb/abstract_controller.rb +0 -399
  55. data/lib/merb/assets.rb +0 -160
  56. data/lib/merb/assets.rb.orig +0 -119
  57. data/lib/merb/boot_loader.rb +0 -286
  58. data/lib/merb/boot_loader.rb.orig +0 -235
  59. data/lib/merb/caching.rb +0 -5
  60. data/lib/merb/caching/action_cache.rb +0 -92
  61. data/lib/merb/caching/fragment_cache.rb +0 -39
  62. data/lib/merb/caching/store/file_cache.rb +0 -90
  63. data/lib/merb/caching/store/memory_cache.rb +0 -85
  64. data/lib/merb/config.rb +0 -290
  65. data/lib/merb/constants.rb +0 -50
  66. data/lib/merb/controller.rb +0 -220
  67. data/lib/merb/cookies.rb +0 -95
  68. data/lib/merb/core_ext.rb +0 -15
  69. data/lib/merb/core_ext/array.rb +0 -0
  70. data/lib/merb/core_ext/class.rb +0 -180
  71. data/lib/merb/core_ext/enumerable.rb +0 -49
  72. data/lib/merb/core_ext/get_args.rb +0 -76
  73. data/lib/merb/core_ext/hash.rb +0 -306
  74. data/lib/merb/core_ext/inflections.rb +0 -112
  75. data/lib/merb/core_ext/inflector.rb +0 -275
  76. data/lib/merb/core_ext/kernel.rb +0 -242
  77. data/lib/merb/core_ext/mash.rb +0 -88
  78. data/lib/merb/core_ext/module.rb +0 -67
  79. data/lib/merb/core_ext/numeric.rb +0 -72
  80. data/lib/merb/core_ext/object.rb +0 -183
  81. data/lib/merb/core_ext/string.rb +0 -53
  82. data/lib/merb/core_ext/symbol.rb +0 -6
  83. data/lib/merb/dispatcher.rb +0 -109
  84. data/lib/merb/drb_server.rb +0 -19
  85. data/lib/merb/erubis_ext.rb +0 -10
  86. data/lib/merb/exceptions.rb +0 -192
  87. data/lib/merb/generators/merb_app/merb_app.rb +0 -22
  88. data/lib/merb/generators/merb_generator_helpers.rb +0 -318
  89. data/lib/merb/generators/merb_plugin.rb +0 -22
  90. data/lib/merb/logger.rb +0 -78
  91. data/lib/merb/mail_controller.rb +0 -268
  92. data/lib/merb/mailer.rb +0 -87
  93. data/lib/merb/mixins/basic_authentication.rb +0 -35
  94. data/lib/merb/mixins/controller.rb +0 -160
  95. data/lib/merb/mixins/erubis_capture.rb +0 -68
  96. data/lib/merb/mixins/general_controller.rb +0 -253
  97. data/lib/merb/mixins/inline_partial.rb +0 -32
  98. data/lib/merb/mixins/render.rb +0 -465
  99. data/lib/merb/mixins/responder.rb +0 -449
  100. data/lib/merb/mixins/view_context.rb +0 -558
  101. data/lib/merb/mixins/web_controller.rb +0 -36
  102. data/lib/merb/mongrel_handler.rb +0 -168
  103. data/lib/merb/part_controller.rb +0 -29
  104. data/lib/merb/plugins.rb +0 -16
  105. data/lib/merb/rack_adapter.rb +0 -37
  106. data/lib/merb/request.rb +0 -465
  107. data/lib/merb/router.rb +0 -646
  108. data/lib/merb/server.rb +0 -169
  109. data/lib/merb/session.rb +0 -23
  110. data/lib/merb/session/cookie_store.rb +0 -118
  111. data/lib/merb/session/mem_cache_session.rb +0 -131
  112. data/lib/merb/session/memory_session.rb +0 -176
  113. data/lib/merb/template.rb +0 -37
  114. data/lib/merb/template/erubis.rb +0 -68
  115. data/lib/merb/template/haml.rb +0 -87
  116. data/lib/merb/template/markaby.rb +0 -59
  117. data/lib/merb/template/xml_builder.rb +0 -50
  118. data/lib/merb/test/fake_request.rb +0 -74
  119. data/lib/merb/test/helper.rb +0 -260
  120. data/lib/merb/test/hpricot.rb +0 -136
  121. data/lib/merb/test/multipart.rb +0 -66
  122. data/lib/merb/test/rspec.rb +0 -18
  123. data/lib/merb/test/rspec_matchers/controller_matchers.rb +0 -117
  124. data/lib/merb/test/rspec_matchers/markup_matchers.rb +0 -98
  125. data/lib/merb/upload_handler.rb +0 -80
  126. data/lib/merb/upload_progress.rb +0 -48
  127. data/lib/merb/version.rb +0 -49
  128. data/lib/merb/view_context.rb +0 -79
  129. data/lib/tasks.rb +0 -7
  130. data/lib/tasks/merb.rake +0 -54
  131. data/merb_default_generators/model/USAGE +0 -0
  132. data/merb_default_generators/model/model_generator.rb +0 -16
  133. data/merb_default_generators/model/templates/new_model_template.erb +0 -5
  134. data/merb_default_generators/resource_controller/USAGE +0 -0
  135. data/merb_default_generators/resource_controller/resource_controller_generator.rb +0 -26
  136. data/merb_default_generators/resource_controller/templates/controller.rb +0 -30
  137. data/merb_default_generators/resource_controller/templates/edit.html.erb +0 -1
  138. data/merb_default_generators/resource_controller/templates/helper.rb +0 -5
  139. data/merb_default_generators/resource_controller/templates/index.html.erb +0 -1
  140. data/merb_default_generators/resource_controller/templates/new.html.erb +0 -1
  141. data/merb_default_generators/resource_controller/templates/show.html.erb +0 -1
  142. data/merb_generators/controller/USAGE +0 -5
  143. data/merb_generators/controller/controller_generator.rb +0 -16
  144. data/merb_generators/controller/templates/controller.rb +0 -8
  145. data/merb_generators/controller/templates/helper.rb +0 -5
  146. data/merb_generators/controller/templates/index.html.erb +0 -3
  147. data/merb_generators/part_controller/USAGE +0 -5
  148. data/merb_generators/part_controller/part_controller_generator.rb +0 -27
  149. data/merb_generators/part_controller/templates/controller.rb +0 -8
  150. data/merb_generators/part_controller/templates/helper.rb +0 -5
  151. data/merb_generators/part_controller/templates/index.html.erb +0 -3
  152. data/merb_generators/resource/USAGE +0 -0
  153. data/merb_generators/resource/resource_generator.rb +0 -67
  154. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +0 -67
  155. data/rspec_generators/merb_controller_test/templates/controller_spec.rb +0 -8
  156. data/rspec_generators/merb_controller_test/templates/edit_spec.rb +0 -12
  157. data/rspec_generators/merb_controller_test/templates/helper_spec.rb +0 -5
  158. data/rspec_generators/merb_controller_test/templates/index_spec.rb +0 -12
  159. data/rspec_generators/merb_controller_test/templates/new_spec.rb +0 -12
  160. data/rspec_generators/merb_controller_test/templates/show_spec.rb +0 -5
  161. data/rspec_generators/merb_model_test/merb_model_test_generator.rb +0 -26
  162. data/rspec_generators/merb_model_test/templates/model_spec_template.erb +0 -7
  163. data/script/destroy +0 -14
  164. data/script/generate +0 -14
  165. data/spec/fixtures/config/environments/environment_config_test.yml +0 -1
  166. data/spec/fixtures/config/merb.yml +0 -18
  167. data/spec/fixtures/controllers/dispatch_spec_controllers.rb +0 -235
  168. data/spec/fixtures/controllers/render_spec_controllers.rb +0 -184
  169. data/spec/fixtures/foo.rb +0 -3
  170. data/spec/fixtures/mailers/views/layout/application.html.erb +0 -3
  171. data/spec/fixtures/mailers/views/layout/application.text.erb +0 -3
  172. data/spec/fixtures/mailers/views/test_mail_controller/eighth.html.erb +0 -1
  173. data/spec/fixtures/mailers/views/test_mail_controller/eighth.text.erb +0 -1
  174. data/spec/fixtures/mailers/views/test_mail_controller/first.html.erb +0 -1
  175. data/spec/fixtures/mailers/views/test_mail_controller/first.text.erb +0 -1
  176. data/spec/fixtures/mailers/views/test_mail_controller/ninth.html.erb +0 -1
  177. data/spec/fixtures/mailers/views/test_mail_controller/ninth.text.erb +0 -1
  178. data/spec/fixtures/mailers/views/test_mail_controller/second.text.erb +0 -1
  179. data/spec/fixtures/mailers/views/test_mail_controller/third.html.erb +0 -1
  180. data/spec/fixtures/models/router_spec_models.rb +0 -30
  181. data/spec/fixtures/parts/views/layout/todo_part.html.erb +0 -3
  182. data/spec/fixtures/parts/views/layout/todo_part.xml.erb +0 -3
  183. data/spec/fixtures/parts/views/todo_part/formatted_output.html.erb +0 -1
  184. data/spec/fixtures/parts/views/todo_part/formatted_output.js.erb +0 -1
  185. data/spec/fixtures/parts/views/todo_part/formatted_output.xml.erb +0 -1
  186. data/spec/fixtures/parts/views/todo_part/list.html.erb +0 -3
  187. data/spec/fixtures/sample.txt +0 -1
  188. data/spec/fixtures/views/erubis.html.erb +0 -1
  189. data/spec/fixtures/views/examples/_erubis.html.erb +0 -1
  190. data/spec/fixtures/views/examples/_haml.html.haml +0 -1
  191. data/spec/fixtures/views/examples/_markaby.html.mab +0 -1
  192. data/spec/fixtures/views/examples/_throw_content.html.erb +0 -6
  193. data/spec/fixtures/views/examples/hello.xml.builder +0 -1
  194. data/spec/fixtures/views/examples/js.js.erb +0 -1
  195. data/spec/fixtures/views/examples/template_catch_content.html.erb +0 -15
  196. data/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb +0 -6
  197. data/spec/fixtures/views/examples/template_throw_content.html.erb +0 -10
  198. data/spec/fixtures/views/examples/template_throw_content_without_block.html.erb +0 -3
  199. data/spec/fixtures/views/exceptions/admin_access_required.html.erb +0 -1
  200. data/spec/fixtures/views/extension_template_controller/_nested_js.js.erb +0 -1
  201. data/spec/fixtures/views/extension_template_controller/_nested_xml.xml.erb +0 -1
  202. data/spec/fixtures/views/extension_template_controller/_render_partial_multiple_times.html.erb +0 -1
  203. data/spec/fixtures/views/extension_template_controller/erubis_templates.html.erb +0 -1
  204. data/spec/fixtures/views/extension_template_controller/erubis_templates.js.erb +0 -1
  205. data/spec/fixtures/views/extension_template_controller/erubis_templates.rhtml +0 -1
  206. data/spec/fixtures/views/extension_template_controller/erubis_templates.xml.erb +0 -1
  207. data/spec/fixtures/views/extension_template_controller/haml_index.html.haml +0 -0
  208. data/spec/fixtures/views/extension_template_controller/haml_templates.html.haml +0 -1
  209. data/spec/fixtures/views/extension_template_controller/haml_templates.js.haml +0 -1
  210. data/spec/fixtures/views/extension_template_controller/haml_templates.xml.haml +0 -1
  211. data/spec/fixtures/views/extension_template_controller/index.html.erb +0 -0
  212. data/spec/fixtures/views/extension_template_controller/markaby_index.html.mab +0 -0
  213. data/spec/fixtures/views/extension_template_controller/markaby_templates.html.mab +0 -1
  214. data/spec/fixtures/views/extension_template_controller/markaby_templates.js.mab +0 -1
  215. data/spec/fixtures/views/extension_template_controller/markaby_templates.xml.mab +0 -1
  216. data/spec/fixtures/views/extension_template_controller/render_multiple_partials.html.erb +0 -4
  217. data/spec/fixtures/views/extension_template_controller/render_nested_js.js.erb +0 -1
  218. data/spec/fixtures/views/extension_template_controller/render_nested_xml.xml.erb +0 -1
  219. data/spec/fixtures/views/haml.html.haml +0 -1
  220. data/spec/fixtures/views/haml.xml.haml +0 -2
  221. data/spec/fixtures/views/layout/application.html.erb +0 -1
  222. data/spec/fixtures/views/layout/application.xml.erb +0 -1
  223. data/spec/fixtures/views/layout/nested/example.html.erb +0 -1
  224. data/spec/fixtures/views/markaby.html.mab +0 -1
  225. data/spec/fixtures/views/nested/example/test.html.erb +0 -1
  226. data/spec/fixtures/views/partials/_erubis.html.erb +0 -1
  227. data/spec/fixtures/views/partials/_erubis_collection.html.erb +0 -1
  228. data/spec/fixtures/views/partials/_erubis_collection_with_locals.html.erb +0 -1
  229. data/spec/fixtures/views/partials/_erubis_new.html.erb +0 -1
  230. data/spec/fixtures/views/partials/_haml.html.haml +0 -1
  231. data/spec/fixtures/views/partials/_haml_collection.html.haml +0 -1
  232. data/spec/fixtures/views/partials/_haml_collection_with_locals.html.haml +0 -1
  233. data/spec/fixtures/views/partials/_haml_new.html.haml +0 -1
  234. data/spec/fixtures/views/partials/_markaby.html.mab +0 -1
  235. data/spec/fixtures/views/partials/_markaby_collection.html.mab +0 -1
  236. data/spec/fixtures/views/partials/_markaby_collection_with_locals.html.mab +0 -1
  237. data/spec/fixtures/views/partials/_markaby_new.html.mab +0 -1
  238. data/spec/fixtures/views/render_object_controller/render_object_with_template.html.erb +0 -1
  239. data/spec/fixtures/views/render_object_controller/render_object_with_template.js.erb +0 -1
  240. data/spec/fixtures/views/render_object_controller/render_object_with_template.xml.erb +0 -1
  241. data/spec/fixtures/views/template_views/interface__buffer_erubis.html.erb +0 -4
  242. data/spec/fixtures/views/template_views/interface__buffer_haml.html.haml +0 -7
  243. data/spec/fixtures/views/template_views/interface__buffer_markaby.html.mab +0 -7
  244. data/spec/fixtures/views/template_views/interface_capture_erubis.html.erb +0 -15
  245. data/spec/fixtures/views/template_views/interface_capture_haml.html.haml +0 -15
  246. data/spec/fixtures/views/template_views/interface_capture_markaby.html.mab +0 -4
  247. data/spec/fixtures/views/template_views/interface_concat_erubis.html.erb +0 -12
  248. data/spec/fixtures/views/template_views/interface_concat_haml.html.haml +0 -11
  249. data/spec/fixtures/views/template_views/interface_concat_markaby.html.mab +0 -14
  250. data/spec/fixtures/views/test.dir/the_template.html.erb +0 -1
  251. data/spec/merb/abstract_controller_spec.rb +0 -38
  252. data/spec/merb/assets_spec.rb +0 -207
  253. data/spec/merb/caching_spec.rb +0 -102
  254. data/spec/merb/config_spec.rb +0 -29
  255. data/spec/merb/controller_filters_spec.rb +0 -253
  256. data/spec/merb/controller_spec.rb +0 -126
  257. data/spec/merb/cookie_store_spec.rb +0 -72
  258. data/spec/merb/cookies_spec.rb +0 -96
  259. data/spec/merb/core_ext/class_spec.rb +0 -97
  260. data/spec/merb/core_ext/enumerable_spec.rb +0 -27
  261. data/spec/merb/core_ext/hash_spec.rb +0 -251
  262. data/spec/merb/core_ext/inflector_spec.rb +0 -34
  263. data/spec/merb/core_ext/kernel_spec.rb +0 -25
  264. data/spec/merb/core_ext/numeric_spec.rb +0 -26
  265. data/spec/merb/core_ext/object_spec.rb +0 -47
  266. data/spec/merb/core_ext/string_spec.rb +0 -22
  267. data/spec/merb/core_ext/symbol_spec.rb +0 -7
  268. data/spec/merb/dependency_spec.rb +0 -22
  269. data/spec/merb/dispatch_spec.rb +0 -528
  270. data/spec/merb/fake_request_spec.rb +0 -80
  271. data/spec/merb/generator_spec.rb +0 -248
  272. data/spec/merb/handler_spec.rb +0 -169
  273. data/spec/merb/mail_controller_spec.rb +0 -177
  274. data/spec/merb/mailer_spec.rb +0 -87
  275. data/spec/merb/multipart_spec.rb +0 -50
  276. data/spec/merb/part_controller_spec.rb +0 -124
  277. data/spec/merb/plugins_spec.rb +0 -80
  278. data/spec/merb/render_spec.rb +0 -469
  279. data/spec/merb/request_spec.rb +0 -287
  280. data/spec/merb/responder_spec.rb +0 -562
  281. data/spec/merb/router_spec.rb +0 -900
  282. data/spec/merb/server_spec.rb +0 -19
  283. data/spec/merb/template_spec.rb +0 -41
  284. data/spec/merb/upload_handler_spec.rb +0 -108
  285. data/spec/merb/version_spec.rb +0 -33
  286. data/spec/merb/view_context_spec.rb +0 -366
  287. data/spec/spec_generator_helper.rb +0 -34
  288. data/spec/spec_helper.rb +0 -101
  289. data/spec/spec_helpers/url_shared_behaviour.rb +0 -112
  290. data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +0 -53
  291. data/test_unit_generators/merb_controller_test/templates/functional_test.rb +0 -17
  292. data/test_unit_generators/merb_controller_test/templates/helper_test.rb +0 -9
  293. data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +0 -29
  294. data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +0 -9
data/lib/merb/router.rb DELETED
@@ -1,646 +0,0 @@
1
- module Merb
2
- class Router
3
- SEGMENT_REGEXP = /(:([a-z_][a-z0-9_]*|:))/
4
- SEGMENT_REGEXP_WITH_BRACKETS = /(:[a-z_]+)(\[(\d+)\])?/
5
- JUST_BRACKETS = /\[(\d+)\]/
6
- PARENTHETICAL_SEGMENT_STRING = "([^\/.,;?]+)".freeze
7
-
8
- @@named_routes = {}
9
- @@routes = []
10
- cattr_accessor :routes, :named_routes
11
-
12
- class << self
13
- def append(&block)
14
- prepare(@@routes, [], &block)
15
- end
16
-
17
- def prepend(&block)
18
- prepare([], @@routes, &block)
19
- end
20
-
21
- def prepare(first = [], last = [], &block)
22
- @@routes = []
23
- yield Behavior.new({}, { :action => 'index' }) # defaults
24
- @@routes = first + @@routes + last
25
- compile
26
- end
27
-
28
- def compiled_statement
29
- @@compiled_statement = "lambda { |request, params|\n"
30
- @@compiled_statement << " cached_path = request.path\n cached_method = request.method.to_s\n "
31
- # @@compiled_statement << " puts cached_path.inspect; puts cached_method.inspect\n"
32
- @@routes.each_with_index { |route, i| @@compiled_statement << route.compile(i == 0) }
33
- @@compiled_statement << " else\n [nil, {}]\n"
34
- @@compiled_statement << " end\n"
35
- @@compiled_statement << "}"
36
- end
37
-
38
- def compile
39
- meta_def(:match, &eval(compiled_statement))
40
- end
41
-
42
- def generate(name, params = {}, fallback = {})
43
- name = name.to_sym
44
- unless @@named_routes.key? name
45
- raise "Named route not found: #{name}"
46
- else
47
- @@named_routes[name].generate(params, fallback)
48
- end
49
- end
50
- end # self
51
-
52
- # Cache procs for future reference in eval statement
53
- class CachedProc
54
- @@index = 0
55
- @@list = []
56
-
57
- attr_accessor :cache, :index
58
-
59
- def initialize(cache)
60
- @cache, @index = cache, CachedProc.register(self)
61
- end
62
-
63
- # Make each CachedProc object embeddable within a string
64
- def to_s
65
- "CachedProc[#{@index}].cache"
66
- end
67
-
68
- class << self
69
- def register(cached_code)
70
- CachedProc[@@index] = cached_code
71
- @@index += 1
72
- @@index - 1
73
- end
74
- def []=(index, code) @@list[index] = code end
75
- def [](index) @@list[index] end
76
- end
77
- end # CachedProc
78
-
79
- class Route
80
- attr_reader :conditions, :conditional_block
81
- attr_reader :params, :behavior, :segments, :index, :symbol
82
-
83
- def initialize(conditions, params, behavior = nil, &conditional_block)
84
- @conditions, @params, @behavior = conditions, params, behavior
85
- @conditional_block = conditional_block
86
- if @behavior && (path = @behavior.merged_original_conditions[:path])
87
- @segments = segments_from_path(path)
88
- end
89
- end
90
-
91
- def to_s
92
- segments.inject('') do |str,seg|
93
- str << (seg.is_a?(Symbol) ? ":#{seg}" : seg)
94
- end
95
- end
96
-
97
- # Registers itself in the Router.routes array
98
- def register
99
- @index = Router.routes.size
100
- Router.routes << self
101
- self
102
- end
103
-
104
- # Get the symbols out of the segments array
105
- def symbol_segments
106
- segments.select{ |s| s.is_a?(Symbol) }
107
- end
108
-
109
- # Turn a path into string and symbol segments so it can be reconstructed, as in the
110
- # case of a named route.
111
- def segments_from_path(path)
112
- # Remove leading ^ and trailing $ from each segment (left-overs from regexp joining)
113
- strip = proc { |str| str.gsub(/^\^/, '').gsub(/\$$/, '') }
114
- segments = []
115
- while match = (path.match(SEGMENT_REGEXP))
116
- segments << strip[match.pre_match] unless match.pre_match.empty?
117
- segments << match[2].intern
118
- path = strip[match.post_match]
119
- end
120
- segments << strip[path] unless path.empty?
121
- segments
122
- end
123
-
124
- # Name this route
125
- def name(symbol = nil)
126
- raise ArgumentError unless (@symbol = symbol).is_a?(Symbol)
127
- Router.named_routes[@symbol] = self
128
- end
129
-
130
- def regexp?
131
- behavior.regexp? || behavior.send(:ancestors).any? { |a| a.regexp? }
132
- end
133
-
134
- # Given a hash of +params+, returns a string using the stored route segments
135
- # for reconstruction of the URL.
136
- def generate(params = {}, fallback = {})
137
- url = @segments.map do |segment|
138
- value =
139
- if segment.is_a? Symbol
140
- if params.is_a? Hash
141
- params[segment] || fallback[segment]
142
- else
143
- if segment == :id && params.respond_to?(:to_param)
144
- params.to_param
145
- elsif params.respond_to?(segment)
146
- params.send(segment)
147
- else
148
- fallback[segment]
149
- end
150
- end
151
- elsif segment.respond_to? :to_s
152
- segment
153
- else
154
- raise "Segment type '#{segment.class}' can't be converted to a string"
155
- end
156
- (value.respond_to?(:to_param) ? value.to_param : value).to_s
157
- end.join
158
- end
159
-
160
- def if_conditions(params_as_string)
161
- cond = []
162
- condition_string = proc do |key, value, regexp_string|
163
- max = Behavior.count_parens_up_to(value.source, value.source.size)
164
- captures = if max == 0 then "" else
165
- " && (" +
166
- (1..max).to_a.map{ |n| "#{key}#{n}" }.join(", ") + " = " +
167
- (1..max).to_a.map{ |n| "$#{n}"}.join(", ") +
168
- ")"
169
- end
170
- " (#{value.inspect} =~ #{regexp_string}" + captures + ")"
171
- end
172
- @conditions.each_pair do |key, value|
173
-
174
- # Note: =~ is slightly faster than .match
175
- cond << case key
176
- when :path then condition_string[key, value, "cached_path"]
177
- when :method then condition_string[key, value, "cached_method"]
178
- else condition_string[key, value, "request.#{key}.to_s"]
179
- end
180
- end
181
- if @conditional_block
182
- str = " # #{@conditional_block.inspect.scan(/@([^>]+)/).flatten.first}\n"
183
- str << " (block_result = #{CachedProc.new(@conditional_block)}.call(request, params.merge({#{params_as_string}})))" if @conditional_block
184
- cond << str
185
- end
186
- cond
187
- end
188
-
189
- def compile(first = false)
190
- code = ""
191
- default_params = { :action => "index" }
192
- get_value = proc do |key|
193
- if default_params.has_key?(key) && params[key][0] != ?"
194
- "#{params[key]} || \"#{default_params[key]}\""
195
- else
196
- "#{params[key]}"
197
- end
198
- end
199
- params_as_string = params.keys.map { |k| "#{k.inspect} => #{get_value[k]}" }.join(', ')
200
- code << " els" unless first
201
- code << "if # #{@behavior.merged_original_conditions.inspect}\n "
202
- code << if_conditions(params_as_string).join(" &&\n ") << "\n"
203
- code << " # then\n"
204
- if @conditional_block
205
- code << " [#{@index.inspect}, block_result]\n"
206
- else
207
- code << " [#{@index.inspect}, {#{params_as_string}}]\n"
208
- end
209
- end
210
-
211
- def behavior_trace
212
- if @behavior
213
- puts @behavior.send(:ancestors).reverse.map{|a| a.inspect}.join("\n"); puts @behavior.inspect; puts
214
- else
215
- puts "No behavior to trace #{self}"
216
- end
217
- end
218
- end # Route
219
-
220
- # The Behavior class is an interim route-building class that ties
221
- # pattern-matching +conditions+ to output parameters, +params+.
222
- class Behavior
223
- attr_reader :placeholders, :conditions, :params
224
- attr_accessor :parent
225
-
226
- class << self
227
- # Count the number of open parentheses in +string+, up to and including +pos+
228
- def count_parens_up_to(string, pos)
229
- string[0..pos].gsub(/[^\(]/, '').size
230
- end
231
-
232
- # Concatenate strings and remove regexp end caps
233
- def concat_without_endcaps(string1, string2)
234
- return nil if !string1 and !string2
235
- return string1 if string2.nil?
236
- return string2 if string1.nil?
237
- s1 = string1[-1] == ?$ ? string1[0..-2] : string1
238
- s2 = string2[0] == ?^ ? string2[1..-1] : string2
239
- s1 + s2
240
- end
241
-
242
- # Join an array's elements into a string using " + " as a joiner, and
243
- # surround string elements in quotes.
244
- def array_to_code(arr)
245
- code = ''
246
- arr.each_with_index do |part, i|
247
- code << ' + ' if i > 0
248
- case part
249
- when Symbol
250
- code << part.to_s
251
- when String
252
- code << %{"#{part}"}
253
- else
254
- raise "Don't know how to compile array part: #{part.class} [#{i}]"
255
- end
256
- end
257
- code
258
- end
259
- end # class << self
260
-
261
- def initialize(conditions = {}, params = {}, parent = nil)
262
- # Must wait until after deducing placeholders to set @params !
263
- @conditions, @params, @parent = conditions, {}, parent
264
- @placeholders = {}
265
- stringify_conditions
266
- copy_original_conditions
267
- deduce_placeholders
268
- @params.merge! params
269
- end
270
-
271
- def add(path, params = {})
272
- match(path).to(params)
273
- end
274
-
275
- # Matches a +path+ and any number of optional request methods as conditions of a route.
276
- # Alternatively, +path+ can be a hash of conditions, in which case +conditions+ is ignored.
277
- # Yields a new instance so that sub-matching may occur.
278
- def match(path = '', conditions = {}, &block)
279
- if path.is_a? Hash
280
- conditions = path
281
- else
282
- conditions[:path] = path
283
- end
284
- match_without_path(conditions, &block)
285
- end
286
-
287
- def match_without_path(conditions = {})
288
- new_behavior = self.class.new(conditions, {}, self)
289
- conditions.delete :path if ['', '^$'].include?(conditions[:path])
290
- yield new_behavior if block_given?
291
- new_behavior
292
- end
293
-
294
- def to_route(params = {}, &conditional_block)
295
- @params.merge! params
296
- Route.new compiled_conditions, compiled_params, self, &conditional_block
297
- end
298
-
299
- # Creates a Route from one or more Behavior objects, unless a +block+ is passed in.
300
- # If a block is passed in, a Behavior object is yielded and further .to operations
301
- # may be called in the block. For example:
302
- #
303
- # r.match('/:controller/:id).to(:action => 'show')
304
- #
305
- # vs.
306
- #
307
- # r.to :controller => 'simple' do |s|
308
- # s.match('/test').to(:action => 'index')
309
- # s.match('/other').to(:action => 'other')
310
- # end
311
- #
312
- def to(params = {}, &block)
313
- if block_given?
314
- new_behavior = self.class.new({}, params, self)
315
- yield new_behavior if block_given?
316
- new_behavior
317
- else
318
- to_route(params).register
319
- end
320
- end
321
-
322
- # Takes a block and stores it for defered conditional routes.
323
- # The block takes the +request+ object and the +params+ hash as parameters
324
- # and should return a hash of params.
325
- #
326
- # r.defer_to do |request, params|
327
- # params.merge :controller => 'here', :action => 'there'
328
- # end
329
- #
330
- def defer_to(params = {}, &conditional_block)
331
- Router.routes << (route = to_route(params, &conditional_block))
332
- route
333
- end
334
-
335
- def default_routes(params = {}, &block)
336
- match(%r{/:controller(/:action(/:id)?)?(\.:format)?}).to(params, &block)
337
- end
338
-
339
- def namespace(name_or_path, &block)
340
- yield self.class.new(:namespace => name_or_path.to_s)
341
- end
342
-
343
- def resources(name, options = {})
344
- namespace = options[:namespace] || merged_params[:namespace] || conditions[:namespace]
345
-
346
- match_path = namespace ? "/#{namespace}/#{name}" : "/#{name}"
347
-
348
- next_level = match match_path
349
-
350
- name_prefix = options.delete :name_prefix
351
-
352
- if name_prefix.nil? && !namespace.nil?
353
- name_prefix = namespace_to_name_prefix namespace
354
- end
355
-
356
- options[:controller] ||= merged_params[:controller] || name.to_s
357
-
358
- singular = name.to_s.singularize
359
-
360
- route_plural_name = "#{name_prefix}#{name}"
361
- route_singular_name = "#{name_prefix}#{singular}"
362
-
363
- behaviors = []
364
-
365
- if member = options.delete(:member)
366
- member.each_pair do |action, methods|
367
- behaviors << Behavior.new(
368
- { :path => %r{^/:id[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
369
- { :action => action.to_s }, next_level
370
- )
371
- next_level.match("/:id/#{action}").to_route.name(:"#{action}_#{route_singular_name}")
372
- end
373
- end
374
-
375
- if collection = options.delete(:collection)
376
- collection.each_pair do |action, methods|
377
- behaviors << Behavior.new(
378
- { :path => %r{^[/;]#{action}(\.:format)?$}, :method => /^(#{[methods].flatten * '|'})$/ },
379
- { :action => action.to_s }, next_level
380
- )
381
- next_level.match("/#{action}").to_route.name(:"#{action}_#{route_plural_name}")
382
- end
383
- end
384
-
385
- routes = many_behaviors_to(behaviors + next_level.send(:resources_behaviors), options)
386
-
387
- # Add names to some routes
388
- [['', :"#{route_plural_name}"],
389
- ['/:id', :"#{route_singular_name}"],
390
- ['/new', :"new_#{route_singular_name}"],
391
- ['/:id/edit', :"edit_#{route_singular_name}"],
392
- ['/:action/:id', :"custom_#{route_singular_name}"]
393
- ].each do |path,name|
394
- next_level.match(path).to_route.name(name)
395
- end
396
-
397
- yield next_level.match("/:#{singular}_id") if block_given?
398
-
399
- routes
400
- end
401
-
402
- def resource(name, options = {})
403
- namespace = options[:namespace] || merged_params[:namespace] || conditions[:namespace]
404
- match_path = namespace ? "/#{namespace}/#{name}" : "/#{name}"
405
- next_level = match match_path
406
-
407
- options[:controller] ||= merged_params[:controller] || name.to_s
408
-
409
- # Do not pass :name_prefix option on to to_resource
410
- name_prefix = options.delete :name_prefix
411
-
412
- if name_prefix.nil? && !namespace.nil?
413
- name_prefix = namespace_to_name_prefix namespace
414
- end
415
-
416
- routes = next_level.to_resource options
417
-
418
- route_name = "#{name_prefix}#{name}"
419
-
420
- next_level.match('').to_route.name(:"#{route_name}")
421
- next_level.match('/new').to_route.name(:"new_#{route_name}")
422
- next_level.match('/edit').to_route.name(:"edit_#{route_name}")
423
-
424
- yield next_level if block_given?
425
-
426
- routes
427
- end
428
-
429
- def to_resources(params = {}, &block)
430
- many_behaviors_to resources_behaviors, params, &block
431
- end
432
-
433
- def to_resource(params = {}, &block)
434
- many_behaviors_to resource_behaviors, params, &block
435
- end
436
-
437
- def merged_original_conditions
438
- if parent.nil?
439
- @original_conditions
440
- else
441
- merged_so_far = parent.merged_original_conditions
442
- if path = Behavior.concat_without_endcaps(merged_so_far[:path], @original_conditions[:path])
443
- merged_so_far.merge(@original_conditions).merge(:path => path)
444
- else
445
- merged_so_far.merge(@original_conditions)
446
- end
447
- end
448
- end
449
-
450
- def merged_conditions
451
- if parent.nil?
452
- @conditions
453
- else
454
- merged_so_far = parent.merged_conditions
455
- if path = Behavior.concat_without_endcaps(merged_so_far[:path], @conditions[:path])
456
- merged_so_far.merge(@conditions).merge(:path => path)
457
- else
458
- merged_so_far.merge(@conditions)
459
- end
460
- end
461
- end
462
-
463
- def merged_params
464
- if parent.nil?
465
- @params
466
- else
467
- parent.merged_params.merge(@params)
468
- end
469
- end
470
-
471
- def merged_placeholders
472
- placeholders = {}
473
- (ancestors.reverse + [self]).each do |a|
474
- a.placeholders.each_pair do |k, pair|
475
- param, place = pair
476
- placeholders[k] = [param, place + (param == :path ? a.total_previous_captures : 0)]
477
- end
478
- end
479
- placeholders
480
- end
481
-
482
- def inspect
483
- "[captures: #{path_captures.inspect}, conditions: #{@original_conditions.inspect}, params: #{@params.inspect}, placeholders: #{@placeholders.inspect}]"
484
- end
485
-
486
- def regexp?
487
- @conditions_have_regexp
488
- end
489
-
490
- protected
491
- def namespace_to_name_prefix(name_or_path)
492
- name_or_path.to_s.tr('/', '_') + '_'
493
- end
494
-
495
- def resources_behaviors(parent = self)
496
- [
497
- Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :get }, { :action => "index" }, parent),
498
- Behavior.new({ :path => %r[^/index(\.:format)?$], :method => :get }, { :action => "index" }, parent),
499
- Behavior.new({ :path => %r[^/new$], :method => :get }, { :action => "new" }, parent),
500
- Behavior.new({ :path => %r[^/?(\.:format)?$], :method => :post }, { :action => "create" }, parent),
501
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :get }, { :action => "show" }, parent),
502
- Behavior.new({ :path => %r[^/:id[;/]edit$], :method => :get }, { :action => "edit" }, parent),
503
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :put }, { :action => "update" }, parent),
504
- Behavior.new({ :path => %r[^/:id(\.:format)?$], :method => :delete }, { :action => "destroy" }, parent)
505
- ]
506
- end
507
-
508
- def resource_behaviors(parent = self)
509
- [
510
- Behavior.new({ :path => %r{^[;/]new$}, :method => :get }, { :action => "new" }, parent),
511
- Behavior.new({ :path => %r{^/?(\.:format)?$}, :method => :post }, { :action => "create" }, parent),
512
- Behavior.new({ :path => %r{^/?(\.:format)?$}, :method => :get }, { :action => "show" }, parent),
513
- Behavior.new({ :path => %r{^[;/]edit$}, :method => :get }, { :action => "edit" }, parent),
514
- Behavior.new({ :path => %r{^/?(\.:format)?$}, :method => :put }, { :action => "update" }, parent),
515
- Behavior.new({ :path => %r{^/?(\.:format)?$}, :method => :delete }, { :action => "destroy" }, parent)
516
- ]
517
- end
518
-
519
- # Creates a series of routes from an array of Behavior objects.
520
- # You can pass in optional +params+, and an optional block that will be
521
- # passed along to the #to method.
522
- def many_behaviors_to(behaviors, params = {}, &conditional_block)
523
- behaviors.map { |b| b.to params, &conditional_block }
524
- end
525
-
526
- # Convert conditions to regular expression string sources for consistency
527
- def stringify_conditions
528
- @conditions_have_regexp = false
529
- @conditions.each_pair do |k,v|
530
- # TODO: Other Regexp special chars
531
-
532
- @conditions[k] = case v
533
- when String,Symbol
534
- if k == :namespace
535
- v.to_s
536
- else
537
- "^#{v.to_s.escape_regexp}$"
538
- end
539
- when Regexp
540
- @conditions_have_regexp = true
541
- v.source
542
- end
543
- end
544
- end
545
-
546
- def copy_original_conditions
547
- @original_conditions = {}
548
- @conditions.each_pair do |key, value|
549
- @original_conditions[key] = value.dup
550
- end
551
- @original_conditions
552
- end
553
-
554
- def deduce_placeholders
555
- @conditions.each_pair do |match_key, source|
556
- while match = SEGMENT_REGEXP.match(source)
557
- source.sub! SEGMENT_REGEXP, PARENTHETICAL_SEGMENT_STRING
558
- unless match[2] == ':' # No need to store anonymous place holders
559
- placeholder_key = match[2].intern
560
- @params[placeholder_key] = "#{match[1]}"
561
- @placeholders[placeholder_key] = [
562
- match_key, Behavior.count_parens_up_to(source, match.offset(1)[0])
563
- ]
564
- end
565
- end
566
- end
567
- end
568
-
569
- def ancestors(list = [])
570
- if parent.nil?
571
- list
572
- else
573
- list.push parent
574
- parent.ancestors list
575
- list
576
- end
577
- end
578
-
579
- # Count the number of regexp captures in the :path condition
580
- def path_captures
581
- return 0 unless conditions[:path]
582
- Behavior.count_parens_up_to(conditions[:path], conditions[:path].size)
583
- end
584
-
585
- def total_previous_captures
586
- ancestors.map{|a| a.path_captures}.inject(0){|sum, n| sum + n}
587
- end
588
-
589
- # def merge_with_ancestors
590
- # self.class.new(merged_conditions, merged_params)
591
- # end
592
-
593
- def compiled_conditions(conditions = merged_conditions)
594
- conditions.inject({}) do |compiled,(k,v)|
595
- compiled.merge k => Regexp.new(v)
596
- end
597
- end
598
-
599
- # Compiles the params hash into 'eval'-able form.
600
- #
601
- # @params = {:controller => "admin/:controller"}
602
- #
603
- # Could become:
604
- #
605
- # { :controller => "'admin/' + matches[:path][1]" }
606
- #
607
- def compiled_params(params = merged_params, placeholders = merged_placeholders)
608
- compiled = {}
609
- params.each_pair do |key, value|
610
- unless value.is_a? String
611
- raise ArgumentError, "param value must be string (#{value.inspect})"
612
- end
613
- result = []
614
- value = value.dup
615
- match = true
616
- while match
617
- if match = SEGMENT_REGEXP_WITH_BRACKETS.match(value)
618
- result << match.pre_match unless match.pre_match.empty?
619
- ph_key = match[1][1..-1].intern
620
- if match[2] # has brackets, e.g. :path[2]
621
- result << :"#{ph_key}#{match[3]}"
622
- else # no brackets, e.g. a named placeholder such as :controller
623
- if place = placeholders[ph_key]
624
- result << :"#{place[0]}#{place[1]}"
625
- else
626
- raise "Placeholder not found while compiling routes: :#{ph_key}"
627
- end
628
- end
629
- value = match.post_match
630
- elsif match = JUST_BRACKETS.match(value)
631
- # This is a reference to :path
632
- result << match.pre_match unless match.pre_match.empty?
633
- result << :"path#{match[1]}"
634
- value = match.post_match
635
- else
636
- result << value unless value.empty?
637
- end
638
- end
639
- compiled[key] = Behavior.array_to_code(result).gsub("\\_", "_")
640
- end
641
- compiled
642
- end
643
- end # Behavior
644
-
645
- end
646
- end