eactionpack 2.1.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 (338) hide show
  1. data/CHANGELOG +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +469 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +146 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller.rb +79 -0
  8. data/lib/action_controller/assertions.rb +69 -0
  9. data/lib/action_controller/assertions/dom_assertions.rb +39 -0
  10. data/lib/action_controller/assertions/model_assertions.rb +20 -0
  11. data/lib/action_controller/assertions/response_assertions.rb +172 -0
  12. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  13. data/lib/action_controller/assertions/selector_assertions.rb +491 -0
  14. data/lib/action_controller/assertions/tag_assertions.rb +130 -0
  15. data/lib/action_controller/base.rb +1288 -0
  16. data/lib/action_controller/benchmarking.rb +94 -0
  17. data/lib/action_controller/caching.rb +72 -0
  18. data/lib/action_controller/caching/actions.rb +144 -0
  19. data/lib/action_controller/caching/fragments.rb +138 -0
  20. data/lib/action_controller/caching/pages.rb +154 -0
  21. data/lib/action_controller/caching/sql_cache.rb +18 -0
  22. data/lib/action_controller/caching/sweeping.rb +97 -0
  23. data/lib/action_controller/cgi_ext.rb +16 -0
  24. data/lib/action_controller/cgi_ext/cookie.rb +110 -0
  25. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  26. data/lib/action_controller/cgi_ext/session.rb +73 -0
  27. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  28. data/lib/action_controller/cgi_process.rb +223 -0
  29. data/lib/action_controller/components.rb +166 -0
  30. data/lib/action_controller/cookies.rb +96 -0
  31. data/lib/action_controller/dispatcher.rb +162 -0
  32. data/lib/action_controller/filters.rb +642 -0
  33. data/lib/action_controller/flash.rb +172 -0
  34. data/lib/action_controller/headers.rb +31 -0
  35. data/lib/action_controller/helpers.rb +221 -0
  36. data/lib/action_controller/http_authentication.rb +124 -0
  37. data/lib/action_controller/integration.rb +634 -0
  38. data/lib/action_controller/layout.rb +309 -0
  39. data/lib/action_controller/mime_responds.rb +173 -0
  40. data/lib/action_controller/mime_type.rb +186 -0
  41. data/lib/action_controller/mime_types.rb +20 -0
  42. data/lib/action_controller/polymorphic_routes.rb +191 -0
  43. data/lib/action_controller/record_identifier.rb +102 -0
  44. data/lib/action_controller/request.rb +764 -0
  45. data/lib/action_controller/request_forgery_protection.rb +140 -0
  46. data/lib/action_controller/request_profiler.rb +169 -0
  47. data/lib/action_controller/rescue.rb +258 -0
  48. data/lib/action_controller/resources.rb +572 -0
  49. data/lib/action_controller/response.rb +76 -0
  50. data/lib/action_controller/routing.rb +387 -0
  51. data/lib/action_controller/routing/builder.rb +203 -0
  52. data/lib/action_controller/routing/optimisations.rb +120 -0
  53. data/lib/action_controller/routing/recognition_optimisation.rb +162 -0
  54. data/lib/action_controller/routing/route.rb +240 -0
  55. data/lib/action_controller/routing/route_set.rb +436 -0
  56. data/lib/action_controller/routing/routing_ext.rb +46 -0
  57. data/lib/action_controller/routing/segments.rb +283 -0
  58. data/lib/action_controller/session/active_record_store.rb +340 -0
  59. data/lib/action_controller/session/cookie_store.rb +166 -0
  60. data/lib/action_controller/session/drb_server.rb +32 -0
  61. data/lib/action_controller/session/drb_store.rb +35 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +98 -0
  63. data/lib/action_controller/session_management.rb +158 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +155 -0
  66. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  67. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  68. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  69. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  70. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  71. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  72. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  73. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  74. data/lib/action_controller/test_case.rb +83 -0
  75. data/lib/action_controller/test_process.rb +526 -0
  76. data/lib/action_controller/url_rewriter.rb +142 -0
  77. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  78. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  79. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  80. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  81. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  82. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  83. data/lib/action_controller/verification.rb +130 -0
  84. data/lib/action_pack.rb +24 -0
  85. data/lib/action_pack/version.rb +9 -0
  86. data/lib/action_view.rb +44 -0
  87. data/lib/action_view/base.rb +335 -0
  88. data/lib/action_view/helpers/active_record_helper.rb +276 -0
  89. data/lib/action_view/helpers/asset_tag_helper.rb +599 -0
  90. data/lib/action_view/helpers/atom_feed_helper.rb +143 -0
  91. data/lib/action_view/helpers/benchmark_helper.rb +33 -0
  92. data/lib/action_view/helpers/cache_helper.rb +40 -0
  93. data/lib/action_view/helpers/capture_helper.rb +161 -0
  94. data/lib/action_view/helpers/date_helper.rb +711 -0
  95. data/lib/action_view/helpers/debug_helper.rb +31 -0
  96. data/lib/action_view/helpers/form_helper.rb +767 -0
  97. data/lib/action_view/helpers/form_options_helper.rb +458 -0
  98. data/lib/action_view/helpers/form_tag_helper.rb +458 -0
  99. data/lib/action_view/helpers/javascript_helper.rb +148 -0
  100. data/lib/action_view/helpers/number_helper.rb +186 -0
  101. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  102. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  103. data/lib/action_view/helpers/sanitize_helper.rb +229 -0
  104. data/lib/action_view/helpers/tag_helper.rb +134 -0
  105. data/lib/action_view/helpers/text_helper.rb +507 -0
  106. data/lib/action_view/helpers/url_helper.rb +573 -0
  107. data/lib/action_view/inline_template.rb +20 -0
  108. data/lib/action_view/partial_template.rb +70 -0
  109. data/lib/action_view/partials.rb +158 -0
  110. data/lib/action_view/template.rb +125 -0
  111. data/lib/action_view/template_error.rb +110 -0
  112. data/lib/action_view/template_finder.rb +176 -0
  113. data/lib/action_view/template_handler.rb +34 -0
  114. data/lib/action_view/template_handlers/builder.rb +27 -0
  115. data/lib/action_view/template_handlers/compilable.rb +128 -0
  116. data/lib/action_view/template_handlers/erb.rb +56 -0
  117. data/lib/action_view/test_case.rb +58 -0
  118. data/lib/actionpack.rb +1 -0
  119. data/test/abstract_unit.rb +36 -0
  120. data/test/active_record_unit.rb +105 -0
  121. data/test/activerecord/active_record_store_test.rb +141 -0
  122. data/test/activerecord/render_partial_with_record_identification_test.rb +191 -0
  123. data/test/adv_attr_test.rb +20 -0
  124. data/test/controller/action_pack_assertions_test.rb +543 -0
  125. data/test/controller/addresses_render_test.rb +43 -0
  126. data/test/controller/assert_select_test.rb +331 -0
  127. data/test/controller/base_test.rb +219 -0
  128. data/test/controller/benchmark_test.rb +32 -0
  129. data/test/controller/caching_test.rb +581 -0
  130. data/test/controller/capture_test.rb +89 -0
  131. data/test/controller/cgi_test.rb +116 -0
  132. data/test/controller/components_test.rb +140 -0
  133. data/test/controller/content_type_test.rb +139 -0
  134. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  135. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  136. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  137. data/test/controller/cookie_test.rb +146 -0
  138. data/test/controller/custom_handler_test.rb +45 -0
  139. data/test/controller/deprecation/deprecated_base_methods_test.rb +37 -0
  140. data/test/controller/dispatcher_test.rb +105 -0
  141. data/test/controller/fake_controllers.rb +33 -0
  142. data/test/controller/fake_models.rb +11 -0
  143. data/test/controller/filter_params_test.rb +49 -0
  144. data/test/controller/filters_test.rb +881 -0
  145. data/test/controller/flash_test.rb +146 -0
  146. data/test/controller/header_test.rb +14 -0
  147. data/test/controller/helper_test.rb +210 -0
  148. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  149. data/test/controller/html-scanner/document_test.rb +148 -0
  150. data/test/controller/html-scanner/node_test.rb +89 -0
  151. data/test/controller/html-scanner/sanitizer_test.rb +269 -0
  152. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  153. data/test/controller/html-scanner/text_node_test.rb +50 -0
  154. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  155. data/test/controller/http_authentication_test.rb +54 -0
  156. data/test/controller/integration_test.rb +252 -0
  157. data/test/controller/integration_upload_test.rb +43 -0
  158. data/test/controller/layout_test.rb +255 -0
  159. data/test/controller/mime_responds_test.rb +514 -0
  160. data/test/controller/mime_type_test.rb +84 -0
  161. data/test/controller/new_render_test.rb +843 -0
  162. data/test/controller/polymorphic_routes_test.rb +174 -0
  163. data/test/controller/record_identifier_test.rb +139 -0
  164. data/test/controller/redirect_test.rb +289 -0
  165. data/test/controller/render_test.rb +484 -0
  166. data/test/controller/request_forgery_protection_test.rb +305 -0
  167. data/test/controller/request_test.rb +928 -0
  168. data/test/controller/rescue_test.rb +517 -0
  169. data/test/controller/resources_test.rb +873 -0
  170. data/test/controller/routing_test.rb +2464 -0
  171. data/test/controller/selector_test.rb +628 -0
  172. data/test/controller/send_file_test.rb +138 -0
  173. data/test/controller/session/cookie_store_test.rb +258 -0
  174. data/test/controller/session/mem_cache_store_test.rb +181 -0
  175. data/test/controller/session_fixation_test.rb +89 -0
  176. data/test/controller/session_management_test.rb +178 -0
  177. data/test/controller/test_test.rb +695 -0
  178. data/test/controller/url_rewriter_test.rb +310 -0
  179. data/test/controller/verification_test.rb +270 -0
  180. data/test/controller/view_paths_test.rb +140 -0
  181. data/test/controller/webservice_test.rb +229 -0
  182. data/test/fixtures/addresses/list.erb +1 -0
  183. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  184. data/test/fixtures/companies.yml +24 -0
  185. data/test/fixtures/company.rb +10 -0
  186. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  187. data/test/fixtures/content_type/render_default_for_js.js.erb +1 -0
  188. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  189. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  190. data/test/fixtures/customers/_customer.html.erb +1 -0
  191. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  192. data/test/fixtures/developer.rb +9 -0
  193. data/test/fixtures/developers.yml +21 -0
  194. data/test/fixtures/developers_projects.yml +13 -0
  195. data/test/fixtures/fun/games/hello_world.erb +1 -0
  196. data/test/fixtures/functional_caching/_partial.erb +3 -0
  197. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  198. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  199. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  200. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  201. data/test/fixtures/helpers/abc_helper.rb +5 -0
  202. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  203. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  204. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  205. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  206. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  207. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  208. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  209. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  210. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  211. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  212. data/test/fixtures/layouts/builder.builder +3 -0
  213. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  214. data/test/fixtures/layouts/standard.erb +1 -0
  215. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  216. data/test/fixtures/layouts/yield.erb +2 -0
  217. data/test/fixtures/mascot.rb +3 -0
  218. data/test/fixtures/mascots.yml +4 -0
  219. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  220. data/test/fixtures/multipart/binary_file +0 -0
  221. data/test/fixtures/multipart/boundary_problem_file +10 -0
  222. data/test/fixtures/multipart/bracketed_param +5 -0
  223. data/test/fixtures/multipart/large_text_file +10 -0
  224. data/test/fixtures/multipart/mixed_files +0 -0
  225. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  226. data/test/fixtures/multipart/single_parameter +5 -0
  227. data/test/fixtures/multipart/text_file +10 -0
  228. data/test/fixtures/override/test/hello_world.erb +1 -0
  229. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  230. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  231. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  232. data/test/fixtures/post_test/post/index.html.erb +1 -0
  233. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  234. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  235. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  236. data/test/fixtures/project.rb +3 -0
  237. data/test/fixtures/projects.yml +7 -0
  238. data/test/fixtures/public/404.html +1 -0
  239. data/test/fixtures/public/500.html +1 -0
  240. data/test/fixtures/public/images/rails.png +0 -0
  241. data/test/fixtures/public/javascripts/application.js +1 -0
  242. data/test/fixtures/public/javascripts/bank.js +1 -0
  243. data/test/fixtures/public/javascripts/robber.js +1 -0
  244. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  245. data/test/fixtures/public/stylesheets/bank.css +1 -0
  246. data/test/fixtures/public/stylesheets/robber.css +1 -0
  247. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  248. data/test/fixtures/replies.yml +15 -0
  249. data/test/fixtures/reply.rb +7 -0
  250. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  251. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  252. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  253. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  254. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  255. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  256. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  257. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  258. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  259. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  260. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  261. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  262. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  263. data/test/fixtures/scope/test/modgreet.erb +1 -0
  264. data/test/fixtures/shared.html.erb +1 -0
  265. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  266. data/test/fixtures/test/_customer.erb +1 -0
  267. data/test/fixtures/test/_customer_counter.erb +1 -0
  268. data/test/fixtures/test/_customer_greeting.erb +1 -0
  269. data/test/fixtures/test/_form.erb +1 -0
  270. data/test/fixtures/test/_hash_greeting.erb +1 -0
  271. data/test/fixtures/test/_hash_object.erb +2 -0
  272. data/test/fixtures/test/_hello.builder +1 -0
  273. data/test/fixtures/test/_labelling_form.erb +1 -0
  274. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  275. data/test/fixtures/test/_partial.erb +1 -0
  276. data/test/fixtures/test/_partial.html.erb +1 -0
  277. data/test/fixtures/test/_partial.js.erb +1 -0
  278. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  279. data/test/fixtures/test/_partial_only.erb +1 -0
  280. data/test/fixtures/test/_person.erb +2 -0
  281. data/test/fixtures/test/_raise.html.erb +1 -0
  282. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  283. data/test/fixtures/test/block_content_for.erb +2 -0
  284. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  285. data/test/fixtures/test/capturing.erb +4 -0
  286. data/test/fixtures/test/content_for.erb +2 -0
  287. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  288. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  289. data/test/fixtures/test/delete_with_js.rjs +2 -0
  290. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  291. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  292. data/test/fixtures/test/erb_content_for.erb +2 -0
  293. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  294. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  295. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  296. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  297. data/test/fixtures/test/greeting.erb +1 -0
  298. data/test/fixtures/test/greeting.js.rjs +1 -0
  299. data/test/fixtures/test/hello.builder +4 -0
  300. data/test/fixtures/test/hello_world.erb +1 -0
  301. data/test/fixtures/test/hello_world_container.builder +3 -0
  302. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  303. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  304. data/test/fixtures/test/hello_xml_world.builder +11 -0
  305. data/test/fixtures/test/list.erb +1 -0
  306. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  307. data/test/fixtures/test/potential_conflicts.erb +4 -0
  308. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  309. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  310. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  311. data/test/fixtures/test/render_to_string_test.erb +1 -0
  312. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  313. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  314. data/test/fixtures/topic.rb +3 -0
  315. data/test/fixtures/topics.yml +22 -0
  316. data/test/fixtures/topics/_topic.html.erb +1 -0
  317. data/test/template/active_record_helper_test.rb +268 -0
  318. data/test/template/asset_tag_helper_test.rb +514 -0
  319. data/test/template/atom_feed_helper_test.rb +179 -0
  320. data/test/template/benchmark_helper_test.rb +60 -0
  321. data/test/template/date_helper_test.rb +1791 -0
  322. data/test/template/deprecated_erb_variable_test.rb +9 -0
  323. data/test/template/erb_util_test.rb +24 -0
  324. data/test/template/form_helper_test.rb +885 -0
  325. data/test/template/form_options_helper_test.rb +1333 -0
  326. data/test/template/form_tag_helper_test.rb +272 -0
  327. data/test/template/javascript_helper_test.rb +73 -0
  328. data/test/template/number_helper_test.rb +97 -0
  329. data/test/template/record_tag_helper_test.rb +54 -0
  330. data/test/template/sanitize_helper_test.rb +48 -0
  331. data/test/template/tag_helper_test.rb +77 -0
  332. data/test/template/template_finder_test.rb +73 -0
  333. data/test/template/template_object_test.rb +95 -0
  334. data/test/template/test_test.rb +56 -0
  335. data/test/template/text_helper_test.rb +367 -0
  336. data/test/template/url_helper_test.rb +544 -0
  337. data/test/testing_sandbox.rb +15 -0
  338. metadata +469 -0
@@ -0,0 +1,176 @@
1
+ module ActionView #:nodoc:
2
+ class TemplateFinder #:nodoc:
3
+
4
+ class InvalidViewPath < StandardError #:nodoc:
5
+ attr_reader :unprocessed_path
6
+ def initialize(path)
7
+ @unprocessed_path = path
8
+ super("Unprocessed view path found: #{@unprocessed_path.inspect}. Set your view paths with #append_view_path, #prepend_view_path, or #view_paths=.")
9
+ end
10
+ end
11
+
12
+ cattr_reader :processed_view_paths
13
+ @@processed_view_paths = Hash.new {|hash, key| hash[key] = []}
14
+
15
+ cattr_reader :file_extension_cache
16
+ @@file_extension_cache = Hash.new {|hash, key|
17
+ hash[key] = Hash.new {|hash, key| hash[key] = []}
18
+ }
19
+
20
+ class << self #:nodoc:
21
+
22
+ # This method is not thread safe. Mutex should be used whenever this is accessed from an instance method
23
+ def process_view_paths(*view_paths)
24
+ view_paths.flatten.compact.each do |dir|
25
+ next if @@processed_view_paths.has_key?(dir)
26
+ @@processed_view_paths[dir] = []
27
+
28
+ #
29
+ # Dir.glob("#{dir}/**/*/**") reads all the directories in view path and templates inside those directories
30
+ # Dir.glob("#{dir}/**") reads templates residing at top level of view path
31
+ #
32
+ (Dir.glob("#{dir}/**/*/**") | Dir.glob("#{dir}/**")).each do |file|
33
+ unless File.directory?(file)
34
+ @@processed_view_paths[dir] << file.split(dir).last.sub(/^\//, '')
35
+
36
+ # Build extension cache
37
+ extension = file.split(".").last
38
+ if template_handler_extensions.include?(extension)
39
+ key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
40
+ @@file_extension_cache[dir][key] << extension
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def update_extension_cache_for(extension)
48
+ @@processed_view_paths.keys.each do |dir|
49
+ Dir.glob("#{dir}/**/*.#{extension}").each do |file|
50
+ key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
51
+ @@file_extension_cache[dir][key] << extension
52
+ end
53
+ end
54
+ end
55
+
56
+ def template_handler_extensions
57
+ ActionView::Template.template_handler_extensions
58
+ end
59
+
60
+ def reload!
61
+ view_paths = @@processed_view_paths.keys
62
+
63
+ @@processed_view_paths = Hash.new {|hash, key| hash[key] = []}
64
+ @@file_extension_cache = Hash.new {|hash, key|
65
+ hash[key] = Hash.new {|hash, key| hash[key] = []}
66
+ }
67
+
68
+ process_view_paths(view_paths)
69
+ end
70
+ end
71
+
72
+ attr_accessor :view_paths
73
+
74
+ def initialize(*args)
75
+ @template = args.shift
76
+
77
+ @view_paths = args.flatten
78
+ @view_paths = @view_paths.respond_to?(:find) ? @view_paths.dup : [*@view_paths].compact
79
+ check_view_paths(@view_paths)
80
+ end
81
+
82
+ def prepend_view_path(path)
83
+ @view_paths.unshift(*path)
84
+
85
+ self.class.process_view_paths(path)
86
+ end
87
+
88
+ def append_view_path(path)
89
+ @view_paths.push(*path)
90
+
91
+ self.class.process_view_paths(path)
92
+ end
93
+
94
+ def view_paths=(path)
95
+ @view_paths = path
96
+ self.class.process_view_paths(path)
97
+ end
98
+
99
+ def pick_template(template_path, extension)
100
+ file_name = "#{template_path}.#{extension}"
101
+ base_path = find_base_path_for(file_name)
102
+ base_path.blank? ? false : "#{base_path}/#{file_name}"
103
+ end
104
+ alias_method :template_exists?, :pick_template
105
+
106
+ def file_exists?(template_path)
107
+ # Clear the forward slash in the beginning if exists
108
+ template_path = template_path.sub(/^\//, '')
109
+
110
+ template_file_name, template_file_extension = path_and_extension(template_path)
111
+
112
+ if template_file_extension
113
+ template_exists?(template_file_name, template_file_extension)
114
+ else
115
+ template_exists?(template_file_name, pick_template_extension(template_path))
116
+ end
117
+ end
118
+
119
+ def find_base_path_for(template_file_name)
120
+ @view_paths.find { |path| @@processed_view_paths[path].include?(template_file_name) }
121
+ end
122
+
123
+ # Returns the view path that the full path resides in.
124
+ def extract_base_path_from(full_path)
125
+ @view_paths.find { |p| full_path[0..p.size - 1] == p }
126
+ end
127
+
128
+ # Gets the extension for an existing template with the given template_path.
129
+ # Returns the format with the extension if that template exists.
130
+ #
131
+ # pick_template_extension('users/show')
132
+ # # => 'html.erb'
133
+ #
134
+ # pick_template_extension('users/legacy')
135
+ # # => "rhtml"
136
+ #
137
+ def pick_template_extension(template_path)
138
+ if extension = find_template_extension_from_handler(template_path, @template.template_format) || find_template_extension_from_first_render
139
+ extension
140
+ elsif @template.template_format == :js && extension = find_template_extension_from_handler(template_path, :html)
141
+ @template.template_format = :html
142
+ extension
143
+ end
144
+ end
145
+
146
+ def find_template_extension_from_handler(template_path, template_format = @template.template_format)
147
+ formatted_template_path = "#{template_path}.#{template_format}"
148
+ view_paths.each do |path|
149
+ if (extensions = @@file_extension_cache[path][formatted_template_path]).any?
150
+ return "#{template_format}.#{extensions.first}"
151
+ elsif (extensions = @@file_extension_cache[path][template_path]).any?
152
+ return extensions.first.to_s
153
+ end
154
+ end
155
+ nil
156
+ end
157
+
158
+ # Splits the path and extension from the given template_path and returns as an array.
159
+ def path_and_extension(template_path)
160
+ template_path_without_extension = template_path.sub(/\.(\w+)$/, '')
161
+ [ template_path_without_extension, $1 ]
162
+ end
163
+
164
+ # Determine the template extension from the <tt>@first_render</tt> filename
165
+ def find_template_extension_from_first_render
166
+ File.basename(@template.first_render.to_s)[/^[^.]+\.(.+)$/, 1]
167
+ end
168
+
169
+ private
170
+ def check_view_paths(view_paths)
171
+ view_paths.each do |path|
172
+ raise InvalidViewPath.new(path) unless @@processed_view_paths.has_key?(path)
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,34 @@
1
+ module ActionView
2
+ class TemplateHandler
3
+
4
+ def self.line_offset
5
+ 0
6
+ end
7
+
8
+ def self.compilable?
9
+ false
10
+ end
11
+
12
+ def initialize(view)
13
+ @view = view
14
+ end
15
+
16
+ def render(template)
17
+ end
18
+
19
+ def compile(template)
20
+ end
21
+
22
+ def compilable?
23
+ self.class.compilable?
24
+ end
25
+
26
+ def line_offset
27
+ self.class.line_offset
28
+ end
29
+
30
+ # Called by CacheHelper#cache
31
+ def cache_fragment(block, name = {}, options = nil)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ require 'builder'
2
+
3
+ module ActionView
4
+ module TemplateHandlers
5
+ class Builder < TemplateHandler
6
+ include Compilable
7
+
8
+ def self.line_offset
9
+ 2
10
+ end
11
+
12
+ def compile(template)
13
+ content_type_handler = (@view.send!(:controller).respond_to?(:response) ? "controller.response" : "controller")
14
+ "#{content_type_handler}.content_type ||= Mime::XML\n" +
15
+ "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" +
16
+ template.source +
17
+ "\nxml.target!\n"
18
+ end
19
+
20
+ def cache_fragment(block, name = {}, options = nil)
21
+ @view.fragment_for(block, name, options) do
22
+ eval('xml.target!', block.binding)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,128 @@
1
+ module ActionView
2
+ module TemplateHandlers
3
+ module Compilable
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethod
7
+
8
+ # Map method names to their compile time
9
+ base.cattr_accessor :compile_time
10
+ base.compile_time = {}
11
+
12
+ # Map method names to the names passed in local assigns so far
13
+ base.cattr_accessor :template_args
14
+ base.template_args = {}
15
+
16
+ # Count the number of inline templates
17
+ base.cattr_accessor :inline_template_count
18
+ base.inline_template_count = 0
19
+ end
20
+
21
+ module ClassMethod
22
+ # If a handler is mixin this module, set compilable to true
23
+ def compilable?
24
+ true
25
+ end
26
+ end
27
+
28
+ def render(template)
29
+ @view.send :execute, template
30
+ end
31
+
32
+ # Compile and evaluate the template's code
33
+ def compile_template(template)
34
+ return unless compile_template?(template)
35
+
36
+ render_symbol = assign_method_name(template)
37
+ render_source = create_template_source(template, render_symbol)
38
+ line_offset = self.template_args[render_symbol].size + self.line_offset
39
+
40
+ begin
41
+ file_name = template.filename || 'compiled-template'
42
+ ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, -line_offset)
43
+ rescue Exception => e # errors from template code
44
+ if @view.logger
45
+ @view.logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}"
46
+ @view.logger.debug "Function body: #{render_source}"
47
+ @view.logger.debug "Backtrace: #{e.backtrace.join("\n")}"
48
+ end
49
+
50
+ raise ActionView::TemplateError.new(template, @view.assigns, e)
51
+ end
52
+
53
+ self.compile_time[render_symbol] = Time.now
54
+ # logger.debug "Compiled template #{file_name || template}\n ==> #{render_symbol}" if logger
55
+ end
56
+
57
+ private
58
+
59
+ # Method to check whether template compilation is necessary.
60
+ # The template will be compiled if the inline template or file has not been compiled yet,
61
+ # if local_assigns has a new key, which isn't supported by the compiled code yet,
62
+ # or if the file has changed on disk and checking file mods hasn't been disabled.
63
+ def compile_template?(template)
64
+ method_key = template.method_key
65
+ render_symbol = @view.method_names[method_key]
66
+
67
+ compile_time = self.compile_time[render_symbol]
68
+ if compile_time && supports_local_assigns?(render_symbol, template.locals)
69
+ if template.filename && !@view.cache_template_loading
70
+ template_changed_since?(template.filename, compile_time)
71
+ end
72
+ else
73
+ true
74
+ end
75
+ end
76
+
77
+ def assign_method_name(template)
78
+ @view.method_names[template.method_key] ||= compiled_method_name(template)
79
+ end
80
+
81
+ def compiled_method_name(template)
82
+ ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment(template.filename)].compact.join('_').to_sym
83
+ end
84
+
85
+ def compiled_method_name_file_path_segment(file_name)
86
+ if file_name
87
+ s = File.expand_path(file_name)
88
+ s.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
89
+ s.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
90
+ s
91
+ else
92
+ (self.inline_template_count += 1).to_s
93
+ end
94
+ end
95
+
96
+ # Method to create the source code for a given template.
97
+ def create_template_source(template, render_symbol)
98
+ body = compile(template)
99
+
100
+ self.template_args[render_symbol] ||= {}
101
+ locals_keys = self.template_args[render_symbol].keys | template.locals.keys
102
+ self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
103
+
104
+ locals_code = ""
105
+ locals_keys.each do |key|
106
+ locals_code << "#{key} = local_assigns[:#{key}]\n"
107
+ end
108
+
109
+ "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
110
+ end
111
+
112
+ # Return true if the given template was compiled for a superset of the keys in local_assigns
113
+ def supports_local_assigns?(render_symbol, local_assigns)
114
+ local_assigns.empty? ||
115
+ ((args = self.template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
116
+ end
117
+
118
+ # Method to handle checking a whether a template has changed since last compile; isolated so that templates
119
+ # not stored on the file system can hook and extend appropriately.
120
+ def template_changed_since?(file_name, compile_time)
121
+ lstat = File.lstat(file_name)
122
+ compile_time < lstat.mtime ||
123
+ (lstat.symlink? && compile_time < File.stat(file_name).mtime)
124
+ end
125
+
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,56 @@
1
+ require 'erb'
2
+
3
+ class ERB
4
+ module Util
5
+ HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;' }
6
+ JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
7
+
8
+ # A utility method for escaping HTML tag characters.
9
+ # This method is also aliased as <tt>h</tt>.
10
+ #
11
+ # In your ERb templates, use this method to escape any unsafe content. For example:
12
+ # <%=h @person.name %>
13
+ #
14
+ # ==== Example:
15
+ # puts html_escape("is a > 0 & a < 10?")
16
+ # # => is a &gt; 0 &amp; a &lt; 10?
17
+ def html_escape(s)
18
+ s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
19
+ end
20
+
21
+ # A utility method for escaping HTML entities in JSON strings.
22
+ # This method is also aliased as <tt>j</tt>.
23
+ #
24
+ # In your ERb templates, use this method to escape any HTML entities:
25
+ # <%=j @person.to_json %>
26
+ #
27
+ # ==== Example:
28
+ # puts json_escape("is a > 0 & a < 10?")
29
+ # # => is a \u003E 0 \u0026 a \u003C 10?
30
+ def json_escape(s)
31
+ s.to_s.gsub(/[&"><]/) { |special| JSON_ESCAPE[special] }
32
+ end
33
+
34
+ alias j json_escape
35
+ module_function :j
36
+ module_function :json_escape
37
+ end
38
+ end
39
+
40
+ module ActionView
41
+ module TemplateHandlers
42
+ class ERB < TemplateHandler
43
+ include Compilable
44
+
45
+ def compile(template)
46
+ ::ERB.new(template.source, nil, @view.erb_trim_mode).src
47
+ end
48
+
49
+ def cache_fragment(block, name = {}, options = nil) #:nodoc:
50
+ @view.fragment_for(block, name, options) do
51
+ eval(ActionView::Base.erb_variable, block.binding)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,58 @@
1
+ require 'active_support/test_case'
2
+
3
+ module ActionView
4
+ class TestCase < ActiveSupport::TestCase
5
+ class_inheritable_accessor :helper_class
6
+ @@helper_class = nil
7
+
8
+ class << self
9
+ def tests(helper_class)
10
+ self.helper_class = helper_class
11
+ end
12
+
13
+ def helper_class
14
+ if current_helper_class = read_inheritable_attribute(:helper_class)
15
+ current_helper_class
16
+ else
17
+ self.helper_class = determine_default_helper_class(name)
18
+ end
19
+ end
20
+
21
+ def determine_default_helper_class(name)
22
+ name.sub(/Test$/, '').constantize
23
+ rescue NameError
24
+ nil
25
+ end
26
+ end
27
+
28
+ ActionView::Base.helper_modules.each do |helper_module|
29
+ include helper_module
30
+ end
31
+ include ActionController::PolymorphicRoutes
32
+ include ActionController::RecordIdentifier
33
+
34
+ setup :setup_with_helper_class
35
+
36
+ def setup_with_helper_class
37
+ if helper_class && !self.class.ancestors.include?(helper_class)
38
+ self.class.send(:include, helper_class)
39
+ end
40
+ end
41
+
42
+ class TestController < ActionController::Base
43
+ attr_accessor :request, :response
44
+
45
+ def initialize
46
+ @request = ActionController::TestRequest.new
47
+ @response = ActionController::TestResponse.new
48
+ end
49
+ end
50
+
51
+ private
52
+ def method_missing(selector, *args)
53
+ controller = TestController.new
54
+ return controller.send!(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
55
+ super
56
+ end
57
+ end
58
+ end