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,20 @@
1
+ module ActionView #:nodoc:
2
+ class InlineTemplate < Template #:nodoc:
3
+
4
+ def initialize(view, source, locals = {}, type = nil)
5
+ @view = view
6
+ @finder = @view.finder
7
+
8
+ @source = source
9
+ @extension = type
10
+ @locals = locals || {}
11
+
12
+ @handler = self.class.handler_class_for_extension(@extension).new(@view)
13
+ end
14
+
15
+ def method_key
16
+ @source
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,70 @@
1
+ module ActionView #:nodoc:
2
+ class PartialTemplate < Template #:nodoc:
3
+
4
+ attr_reader :variable_name, :object
5
+
6
+ def initialize(view, partial_path, object = nil, locals = {})
7
+ @path, @variable_name = extract_partial_name_and_path(view, partial_path)
8
+ super(view, @path, true, locals)
9
+ add_object_to_local_assigns!(object)
10
+
11
+ # This is needed here in order to compile template with knowledge of 'counter'
12
+ initialize_counter
13
+
14
+ # Prepare early. This is a performance optimization for partial collections
15
+ prepare!
16
+ end
17
+
18
+ def render
19
+ ActionController::Base.benchmark("Rendered #{@path}", Logger::DEBUG, false) do
20
+ @handler.render(self)
21
+ end
22
+ end
23
+
24
+ def render_member(object)
25
+ @locals[:object] = @locals[@variable_name] = object
26
+
27
+ template = render_template
28
+ @locals[@counter_name] += 1
29
+ @locals.delete(@variable_name)
30
+ @locals.delete(:object)
31
+
32
+ template
33
+ end
34
+
35
+ def counter=(num)
36
+ @locals[@counter_name] = num
37
+ end
38
+
39
+ private
40
+
41
+ def add_object_to_local_assigns!(object)
42
+ @locals[:object] ||=
43
+ @locals[@variable_name] ||=
44
+ if object.is_a?(ActionView::Base::ObjectWrapper)
45
+ object.value
46
+ else
47
+ object
48
+ end || @view.controller.instance_variable_get("@#{variable_name}")
49
+ end
50
+
51
+ def extract_partial_name_and_path(view, partial_path)
52
+ path, partial_name = partial_pieces(view, partial_path)
53
+ [File.join(path, "_#{partial_name}"), partial_name.split('/').last.split('.').first.to_sym]
54
+ end
55
+
56
+ def partial_pieces(view, partial_path)
57
+ if partial_path.include?('/')
58
+ return File.dirname(partial_path), File.basename(partial_path)
59
+ else
60
+ return view.controller.class.controller_path, partial_path
61
+ end
62
+ end
63
+
64
+ def initialize_counter
65
+ @counter_name ||= "#{@variable_name}_counter".to_sym
66
+ @locals[@counter_name] = 0
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,158 @@
1
+ module ActionView
2
+ # There's also a convenience method for rendering sub templates within the current controller that depends on a single object
3
+ # (we call this kind of sub templates for partials). It relies on the fact that partials should follow the naming convention of being
4
+ # prefixed with an underscore -- as to separate them from regular templates that could be rendered on their own.
5
+ #
6
+ # In a template for Advertiser#account:
7
+ #
8
+ # <%= render :partial => "account" %>
9
+ #
10
+ # This would render "advertiser/_account.erb" and pass the instance variable @account in as a local variable +account+ to
11
+ # the template for display.
12
+ #
13
+ # In another template for Advertiser#buy, we could have:
14
+ #
15
+ # <%= render :partial => "account", :locals => { :account => @buyer } %>
16
+ #
17
+ # <% for ad in @advertisements %>
18
+ # <%= render :partial => "ad", :locals => { :ad => ad } %>
19
+ # <% end %>
20
+ #
21
+ # This would first render "advertiser/_account.erb" with @buyer passed in as the local variable +account+, then render
22
+ # "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display.
23
+ #
24
+ # == Rendering a collection of partials
25
+ #
26
+ # The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub
27
+ # template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders
28
+ # a partial by the same name as the elements contained within. So the three-lined example in "Using partials" can be rewritten
29
+ # with a single line:
30
+ #
31
+ # <%= render :partial => "ad", :collection => @advertisements %>
32
+ #
33
+ # This will render "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display. An iteration counter
34
+ # will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the
35
+ # example above, the template would be fed +ad_counter+.
36
+ #
37
+ # NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also just keep domain objects,
38
+ # like Active Records, in there.
39
+ #
40
+ # == Rendering shared partials
41
+ #
42
+ # Two controllers can share a set of partials and render them like this:
43
+ #
44
+ # <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %>
45
+ #
46
+ # This will render the partial "advertisement/_ad.erb" regardless of which controller this is being called from.
47
+ #
48
+ # == Rendering partials with layouts
49
+ #
50
+ # Partials can have their own layouts applied to them. These layouts are different than the ones that are specified globally
51
+ # for the entire action, but they work in a similar fashion. Imagine a list with two types of users:
52
+ #
53
+ # <%# app/views/users/index.html.erb &>
54
+ # Here's the administrator:
55
+ # <%= render :partial => "user", :layout => "administrator", :locals => { :user => administrator } %>
56
+ #
57
+ # Here's the editor:
58
+ # <%= render :partial => "user", :layout => "editor", :locals => { :user => editor } %>
59
+ #
60
+ # <%# app/views/users/_user.html.erb &>
61
+ # Name: <%= user.name %>
62
+ #
63
+ # <%# app/views/users/_administrator.html.erb &>
64
+ # <div id="administrator">
65
+ # Budget: $<%= user.budget %>
66
+ # <%= yield %>
67
+ # </div>
68
+ #
69
+ # <%# app/views/users/_editor.html.erb &>
70
+ # <div id="editor">
71
+ # Deadline: $<%= user.deadline %>
72
+ # <%= yield %>
73
+ # </div>
74
+ #
75
+ # ...this will return:
76
+ #
77
+ # Here's the administrator:
78
+ # <div id="administrator">
79
+ # Budget: $<%= user.budget %>
80
+ # Name: <%= user.name %>
81
+ # </div>
82
+ #
83
+ # Here's the editor:
84
+ # <div id="editor">
85
+ # Deadline: $<%= user.deadline %>
86
+ # Name: <%= user.name %>
87
+ # </div>
88
+ #
89
+ # You can also apply a layout to a block within any template:
90
+ #
91
+ # <%# app/views/users/_chief.html.erb &>
92
+ # <% render(:layout => "administrator", :locals => { :user => chief }) do %>
93
+ # Title: <%= chief.title %>
94
+ # <% end %>
95
+ #
96
+ # ...this will return:
97
+ #
98
+ # <div id="administrator">
99
+ # Budget: $<%= user.budget %>
100
+ # Title: <%= chief.name %>
101
+ # </div>
102
+ #
103
+ # As you can see, the <tt>:locals</tt> hash is shared between both the partial and its layout.
104
+ module Partials
105
+ private
106
+ def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
107
+ case partial_path
108
+ when String, Symbol, NilClass
109
+ # Render the template
110
+ ActionView::PartialTemplate.new(self, partial_path, object_assigns, local_assigns).render_template
111
+ when ActionView::Helpers::FormBuilder
112
+ builder_partial_path = partial_path.class.to_s.demodulize.underscore.sub(/_builder$/, '')
113
+ render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path))
114
+ when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope
115
+ if partial_path.any?
116
+ collection = partial_path
117
+ render_partial_collection(nil, collection, nil, local_assigns)
118
+ else
119
+ ""
120
+ end
121
+ else
122
+ render_partial(ActionController::RecordIdentifier.partial_path(partial_path, controller.class.controller_path), partial_path, local_assigns)
123
+ end
124
+ end
125
+
126
+ def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}) #:nodoc:
127
+ return " " if collection.empty?
128
+
129
+ local_assigns = local_assigns ? local_assigns.clone : {}
130
+ spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
131
+
132
+ if partial_path.nil?
133
+ render_partial_collection_with_unknown_partial_path(collection, local_assigns)
134
+ else
135
+ render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns)
136
+ end.join(spacer)
137
+ end
138
+
139
+ def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns)
140
+ template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns)
141
+ collection.map do |element|
142
+ template.render_member(element)
143
+ end
144
+ end
145
+
146
+ def render_partial_collection_with_unknown_partial_path(collection, local_assigns)
147
+ templates = Hash.new
148
+ i = 0
149
+ collection.map do |element|
150
+ partial_path = ActionController::RecordIdentifier.partial_path(element, controller.class.controller_path)
151
+ template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns)
152
+ template.counter = i
153
+ i += 1
154
+ template.render_member(element)
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,125 @@
1
+ module ActionView #:nodoc:
2
+ class Template #:nodoc:
3
+
4
+ attr_accessor :locals
5
+ attr_reader :handler, :path, :extension, :filename, :path_without_extension, :method
6
+
7
+ def initialize(view, path, use_full_path, locals = {})
8
+ @view = view
9
+ @finder = @view.finder
10
+ # Clear the forward slash at the beginning if exists
11
+ @path = use_full_path ? path.sub(/^\//, '') : path
12
+ @view.first_render ||= @path
13
+ @source = nil # Don't read the source until we know that it is required
14
+ set_extension_and_file_name(use_full_path)
15
+
16
+ @locals = locals || {}
17
+ @handler = self.class.handler_class_for_extension(@extension).new(@view)
18
+ end
19
+
20
+ def render_template
21
+ render
22
+ rescue Exception => e
23
+ raise e unless filename
24
+ if TemplateError === e
25
+ e.sub_template_of(filename)
26
+ raise e
27
+ else
28
+ raise TemplateError.new(self, @view.assigns, e)
29
+ end
30
+ end
31
+
32
+ def render
33
+ prepare!
34
+ @handler.render(self)
35
+ end
36
+
37
+ def source
38
+ @source ||= File.read(self.filename)
39
+ end
40
+
41
+ def method_key
42
+ @filename
43
+ end
44
+
45
+ def base_path_for_exception
46
+ @finder.find_base_path_for("#{@path_without_extension}.#{@extension}") || @finder.view_paths.first
47
+ end
48
+
49
+ def prepare!
50
+ @view.send :evaluate_assigns
51
+ @view.current_render_extension = @extension
52
+
53
+ if @handler.compilable?
54
+ @handler.compile_template(self) # compile the given template, if necessary
55
+ @method = @view.method_names[method_key] # Set the method name for this template and run it
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def set_extension_and_file_name(use_full_path)
62
+ @path_without_extension, @extension = @finder.path_and_extension(@path)
63
+ if use_full_path
64
+ if @extension
65
+ @filename = @finder.pick_template(@path_without_extension, @extension)
66
+ else
67
+ @extension = @finder.pick_template_extension(@path).to_s
68
+ raise_missing_template_exception unless @extension
69
+
70
+ @filename = @finder.pick_template(@path, @extension)
71
+ @extension = @extension.gsub(/^.+\./, '') # strip off any formats
72
+ end
73
+ else
74
+ @filename = @path
75
+ end
76
+
77
+ raise_missing_template_exception if @filename.blank?
78
+ end
79
+
80
+ def raise_missing_template_exception
81
+ full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb"
82
+ display_paths = @finder.view_paths.join(':')
83
+ template_type = (@path =~ /layouts/i) ? 'layout' : 'template'
84
+ raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}")
85
+ end
86
+
87
+ # Template Handlers
88
+
89
+ @@template_handlers = HashWithIndifferentAccess.new
90
+ @@default_template_handlers = nil
91
+
92
+ # Register a class that knows how to handle template files with the given
93
+ # extension. This can be used to implement new template types.
94
+ # The constructor for the class must take the ActiveView::Base instance
95
+ # as a parameter, and the class must implement a +render+ method that
96
+ # takes the contents of the template to render as well as the Hash of
97
+ # local assigns available to the template. The +render+ method ought to
98
+ # return the rendered template as a string.
99
+ def self.register_template_handler(extension, klass)
100
+ @@template_handlers[extension.to_sym] = klass
101
+ TemplateFinder.update_extension_cache_for(extension.to_s)
102
+ end
103
+
104
+ def self.template_handler_extensions
105
+ @@template_handlers.keys.map(&:to_s).sort
106
+ end
107
+
108
+ def self.register_default_template_handler(extension, klass)
109
+ register_template_handler(extension, klass)
110
+ @@default_template_handlers = klass
111
+ end
112
+
113
+ def self.handler_class_for_extension(extension)
114
+ (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
115
+ end
116
+
117
+ register_default_template_handler :erb, TemplateHandlers::ERB
118
+ register_template_handler :builder, TemplateHandlers::Builder
119
+
120
+ # TODO: Depreciate old template extensions
121
+ register_template_handler :rhtml, TemplateHandlers::ERB
122
+ register_template_handler :rxml, TemplateHandlers::Builder
123
+
124
+ end
125
+ end
@@ -0,0 +1,110 @@
1
+ module ActionView
2
+ # The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a
3
+ # bunch of intimate details and uses it to report a very precise exception message.
4
+ class TemplateError < ActionViewError #:nodoc:
5
+ SOURCE_CODE_RADIUS = 3
6
+
7
+ attr_reader :original_exception
8
+
9
+ def initialize(template, assigns, original_exception)
10
+ @base_path = template.base_path_for_exception
11
+ @assigns, @source, @original_exception = assigns.dup, template.source, original_exception
12
+ @file_path = template.filename
13
+ @backtrace = compute_backtrace
14
+ end
15
+
16
+ def message
17
+ ActiveSupport::Deprecation.silence { original_exception.message }
18
+ end
19
+
20
+ def clean_backtrace
21
+ original_exception.clean_backtrace
22
+ end
23
+
24
+ def sub_template_message
25
+ if @sub_templates
26
+ "Trace of template inclusion: " +
27
+ @sub_templates.collect { |template| strip_base_path(template) }.join(", ")
28
+ else
29
+ ""
30
+ end
31
+ end
32
+
33
+ def source_extract(indentation = 0)
34
+ return unless num = line_number
35
+ num = num.to_i
36
+
37
+ source_code = IO.readlines(@file_path)
38
+
39
+ start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
40
+ end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
41
+
42
+ indent = ' ' * indentation
43
+ line_counter = start_on_line
44
+ return unless source_code = source_code[start_on_line..end_on_line]
45
+
46
+ source_code.sum do |line|
47
+ line_counter += 1
48
+ "#{indent}#{line_counter}: #{line}"
49
+ end
50
+ end
51
+
52
+ def sub_template_of(template_path)
53
+ @sub_templates ||= []
54
+ @sub_templates << template_path
55
+ end
56
+
57
+ def line_number
58
+ @line_number ||=
59
+ if file_name
60
+ regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
61
+
62
+ $1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp }
63
+ end
64
+ end
65
+
66
+ def file_name
67
+ stripped = strip_base_path(@file_path)
68
+ stripped.slice!(0,1) if stripped[0] == ?/
69
+ stripped
70
+ end
71
+
72
+ def to_s
73
+ "\n\n#{self.class} (#{message}) #{source_location}:\n" +
74
+ "#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n"
75
+ end
76
+
77
+ # don't do anything nontrivial here. Any raised exception from here becomes fatal
78
+ # (and can't be rescued).
79
+ def backtrace
80
+ @backtrace
81
+ end
82
+
83
+ private
84
+ def compute_backtrace
85
+ [
86
+ "#{source_location.capitalize}\n\n#{source_extract(4)}\n " +
87
+ clean_backtrace.join("\n ")
88
+ ]
89
+ end
90
+
91
+ def strip_base_path(path)
92
+ stripped_path = File.expand_path(path).gsub(@base_path, "")
93
+ stripped_path.gsub!(/^#{Regexp.escape File.expand_path(RAILS_ROOT)}/, '') if defined?(RAILS_ROOT)
94
+ stripped_path
95
+ end
96
+
97
+ def source_location
98
+ if line_number
99
+ "on line ##{line_number} of "
100
+ else
101
+ 'in '
102
+ end + file_name
103
+ end
104
+ end
105
+ end
106
+
107
+ if defined?(Exception::TraceSubstitutions)
108
+ Exception::TraceSubstitutions << [/:in\s+`_run_(html|xml).*'\s*$/, '']
109
+ Exception::TraceSubstitutions << [%r{^\s*#{Regexp.escape RAILS_ROOT}/}, ''] if defined?(RAILS_ROOT)
110
+ end