Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git://github.com/rails/rails

  • Loading branch information...
commit 2bcc2ebf44b59e46c104c92d621e8051c97bfcf5 2 parents f5774e3 + 8398f21
Mikel Lindsaar mikel authored
Showing with 5,902 additions and 3,036 deletions.
  1. +6 −3 Gemfile
  2. +4 −4 Rakefile
  3. +6 −3 actionmailer/lib/action_mailer/base.rb
  4. +3 −9 actionmailer/lib/action_mailer/collector.rb
  5. +2 −4 actionmailer/lib/action_mailer/old_api.rb
  6. +2 −2 actionmailer/lib/action_mailer/railtie.rb
  7. +4 −2 actionmailer/lib/action_mailer/railties/log_subscriber.rb
  8. +20 −1 actionmailer/test/abstract_unit.rb
  9. +38 −22 actionmailer/test/base_test.rb
  10. +1 −0  actionmailer/test/fixtures/base_mailer/explicit_multipart_with_one_template.erb
  11. 0  actionmailer/test/fixtures/{test_mailer → url_test_mailer}/signed_up_with_url.erb
  12. +0 −22 actionmailer/test/old_base/mail_layout_test.rb
  13. +4 −5 actionmailer/test/old_base/mail_service_test.rb
  14. +4 −12 actionmailer/test/old_base/url_test.rb
  15. +1 −0  actionpack/lib/abstract_controller.rb
  16. +21 −0 actionpack/lib/abstract_controller/assigns.rb
  17. +1 −9 actionpack/lib/abstract_controller/helpers.rb
  18. +20 −7 actionpack/lib/abstract_controller/layouts.rb
  19. +52 −24 actionpack/lib/abstract_controller/rendering.rb
  20. +1 −5 actionpack/lib/abstract_controller/view_paths.rb
  21. +7 −2 actionpack/lib/action_controller/base.rb
  22. +17 −11 actionpack/lib/action_controller/caching/actions.rb
  23. +5 −17 actionpack/lib/action_controller/caching/fragments.rb
  24. +1 −1  actionpack/lib/action_controller/deprecated/base.rb
  25. +12 −2 actionpack/lib/action_controller/metal.rb
  26. +0 −9 actionpack/lib/action_controller/metal/compatibility.rb
  27. +2 −1  actionpack/lib/action_controller/metal/mime_responds.rb
  28. +2 −4 actionpack/lib/action_controller/metal/rack_delegation.rb
  29. +1 −1  actionpack/lib/action_controller/metal/redirecting.rb
  30. +2 −1  actionpack/lib/action_controller/metal/renderers.rb
  31. +11 −10 actionpack/lib/action_controller/metal/rendering.rb
  32. +1 −1  actionpack/lib/action_controller/metal/request_forgery_protection.rb
  33. +2 −0  actionpack/lib/action_controller/metal/responder.rb
  34. +10 −7 actionpack/lib/action_controller/railtie.rb
  35. +1 −1  actionpack/lib/action_controller/railties/url_helpers.rb
  36. +102 −1 actionpack/lib/action_controller/test_case.rb
  37. +0 −1  actionpack/lib/action_dispatch/http/filter_parameters.rb
  38. +1 −7 actionpack/lib/action_dispatch/http/mime_type.rb
  39. +1 −0  actionpack/lib/action_dispatch/middleware/cookies.rb
  40. +0 −14 actionpack/lib/action_dispatch/middleware/show_exceptions.rb
  41. +2 −3 actionpack/lib/action_dispatch/railtie.rb
  42. +1 −0  actionpack/lib/action_dispatch/routing.rb
  43. +45 −24 actionpack/lib/action_dispatch/routing/mapper.rb
  44. +20 −6 actionpack/lib/action_dispatch/routing/route_set.rb
  45. +1 −1  actionpack/lib/action_dispatch/routing/url_for.rb
  46. +0 −52 actionpack/lib/action_dispatch/testing/assertions/response.rb
  47. +16 −2 actionpack/lib/action_dispatch/testing/assertions/routing.rb
  48. +9 −32 actionpack/lib/action_dispatch/testing/integration.rb
  49. +3 −1 actionpack/lib/action_view.rb
  50. +14 −64 actionpack/lib/action_view/base.rb
  51. +0 −2  actionpack/lib/action_view/context.rb
  52. +26 −24 actionpack/lib/action_view/helpers.rb
  53. +7 −2 actionpack/lib/action_view/helpers/active_model_helper.rb
  54. +41 −44 actionpack/lib/action_view/helpers/asset_tag_helper.rb
  55. +22 −1 actionpack/lib/action_view/helpers/cache_helper.rb
  56. +18 −16 actionpack/lib/action_view/helpers/capture_helper.rb
  57. +0 −52 actionpack/lib/action_view/helpers/deprecated_block_helpers.rb
  58. +39 −39 actionpack/lib/action_view/helpers/form_helper.rb
  59. +1 −1  actionpack/lib/action_view/helpers/form_options_helper.rb
  60. +5 −5 actionpack/lib/action_view/helpers/form_tag_helper.rb
  61. +88 −2 actionpack/lib/action_view/helpers/javascript_helper.rb
  62. +298 −104 actionpack/lib/action_view/helpers/number_helper.rb
  63. +9 −43 actionpack/lib/action_view/helpers/prototype_helper.rb
  64. +4 −4 actionpack/lib/action_view/helpers/record_tag_helper.rb
  65. +2 −2 actionpack/lib/action_view/helpers/tag_helper.rb
  66. +4 −4 actionpack/lib/action_view/helpers/text_helper.rb
  67. +4 −3 actionpack/lib/action_view/helpers/translation_helper.rb
  68. +11 −5 actionpack/lib/action_view/helpers/url_helper.rb
  69. +45 −6 actionpack/lib/action_view/locale/en.yml
  70. +92 −53 actionpack/lib/action_view/lookup_context.rb
  71. +10 −2 actionpack/lib/action_view/railtie.rb
  72. +17 −9 actionpack/lib/action_view/render/layouts.rb
  73. +4 −4 actionpack/lib/action_view/render/partials.rb
  74. +14 −42 actionpack/lib/action_view/render/rendering.rb
  75. +10 −14 actionpack/lib/action_view/template.rb
  76. +22 −2 actionpack/lib/action_view/template/error.rb
  77. +21 −41 actionpack/lib/action_view/template/handlers/erb.rb
  78. +1 −2  actionpack/lib/action_view/template/handlers/rjs.rb
  79. +14 −31 actionpack/lib/action_view/template/resolver.rb
  80. +6 −8 actionpack/lib/action_view/template/text.rb
  81. +6 −23 actionpack/lib/action_view/test_case.rb
  82. +52 −104 actionpack/test/abstract/layouts_test.rb
  83. +13 −41 actionpack/test/abstract_unit.rb
  84. +7 −6 actionpack/test/controller/action_pack_assertions_test.rb
  85. +33 −6 actionpack/test/controller/base_test.rb
  86. +30 −21 actionpack/test/controller/caching_test.rb
  87. +11 −0 actionpack/test/controller/cookie_test.rb
  88. +2 −2 actionpack/test/controller/filters_test.rb
  89. +3 −5 actionpack/test/controller/integration_test.rb
  90. +8 −8 actionpack/test/controller/layout_test.rb
  91. +1 −1  actionpack/test/controller/mime_responds_test.rb
  92. +27 −0 actionpack/test/controller/new_base/bare_metal_test.rb
  93. +4 −2 actionpack/test/controller/new_base/metal_test.rb
  94. +1 −1  actionpack/test/controller/new_base/middleware_test.rb
  95. +2 −2 actionpack/test/controller/new_base/render_action_test.rb
  96. +19 −1 actionpack/test/controller/new_base/render_rjs_test.rb
  97. +24 −14 actionpack/test/controller/render_test.rb
  98. +7 −0 actionpack/test/controller/resources_test.rb
  99. +4 −4 actionpack/test/dispatch/mount_test.rb
  100. +55 −3 actionpack/test/dispatch/routing_test.rb
  101. +6 −1 actionpack/test/dispatch/url_generation_test.rb
  102. +2 −2 actionpack/test/fixtures/functional_caching/_partial.erb
  103. +2 −2 actionpack/test/fixtures/functional_caching/formatted_fragment_cached.html.erb
  104. +1 −1  actionpack/test/fixtures/functional_caching/fragment_cached.html.erb
  105. +1 −1  actionpack/test/fixtures/functional_caching/inline_fragment_cached.html.erb
  106. +2 −2 actionpack/test/fixtures/layouts/block_with_layout.erb
  107. +1 −0  actionpack/test/fixtures/test/array_translation.erb
  108. +3 −0  actionpack/test/fixtures/test/deprecated_nested_layout.erb
  109. +1 −1  actionpack/test/fixtures/test/nested_layout.erb
  110. +1 −0  actionpack/test/fixtures/test/scoped_array_translation.erb
  111. +1 −1  actionpack/test/fixtures/test/using_layout_around_block.html.erb
  112. +8 −5 actionpack/test/lib/fixture_template.rb
  113. +18 −0 actionpack/test/template/active_model_helper_test.rb
  114. +21 −19 actionpack/test/template/asset_tag_helper_test.rb
  115. +1 −2  actionpack/test/template/body_parts_test.rb
  116. +106 −0 actionpack/test/template/capture_helper_test.rb
  117. +11 −0 actionpack/test/template/erb/form_for_test.rb
  118. +30 −0 actionpack/test/template/erb/helper.rb
  119. +19 −41 actionpack/test/template/erb/tag_helper_test.rb
  120. +30 −1 actionpack/test/template/javascript_helper_test.rb
  121. +178 −0 actionpack/test/template/lookup_context_test.rb
  122. +77 −51 actionpack/test/template/number_helper_i18n_test.rb
  123. +263 −32 actionpack/test/template/number_helper_test.rb
  124. +10 −9 actionpack/test/template/output_buffer_test.rb
  125. +9 −1 actionpack/test/template/render_test.rb
  126. +14 −1 actionpack/test/template/translation_helper_test.rb
  127. +1 −4 actionpack/test/template/url_helper_test.rb
  128. +37 −48 activemodel/README
  129. +16 −4 activemodel/lib/active_model/attribute_methods.rb
  130. +4 −3 activemodel/lib/active_model/callbacks.rb
  131. +16 −19 activemodel/lib/active_model/dirty.rb
  132. +2 −1  activemodel/lib/active_model/errors.rb
  133. +2 −0  activemodel/lib/active_model/naming.rb
  134. +4 −3 activemodel/lib/active_model/serializers/xml.rb
  135. +2 −2 activemodel/lib/active_model/validations.rb
  136. +2 −1  activemodel/lib/active_model/validator.rb
  137. +30 −0 activemodel/test/cases/dirty_test.rb
  138. +1 −1  activerecord/activerecord.gemspec
  139. +5 −0 activerecord/lib/active_record/aggregations.rb
  140. +24 −24 activerecord/lib/active_record/associations.rb
  141. +1 −0  activerecord/lib/active_record/associations/association_collection.rb
  142. +2 −1  activerecord/lib/active_record/associations/association_proxy.rb
  143. +4 −0 activerecord/lib/active_record/associations/has_many_association.rb
  144. +9 −9 activerecord/lib/active_record/attribute_methods/dirty.rb
  145. +22 −30 activerecord/lib/active_record/base.rb
  146. +10 −0 activerecord/lib/active_record/callbacks.rb
  147. +23 −0 activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
  148. +13 −1 activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
  149. +1 −3 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  150. +3 −0  activerecord/lib/active_record/dynamic_finder_match.rb
  151. +4 −2 activerecord/lib/active_record/migration.rb
  152. +5 −2 activerecord/lib/active_record/nested_attributes.rb
  153. +2 −3 activerecord/lib/active_record/railtie.rb
  154. +1 −1  activerecord/lib/active_record/railties/databases.rake
  155. +6 −1 activerecord/lib/active_record/railties/log_subscriber.rb
  156. +5 −3 activerecord/lib/active_record/reflection.rb
  157. +6 −1 activerecord/lib/active_record/relation.rb
  158. +11 −2 activerecord/lib/active_record/relation/finder_methods.rb
  159. +5 −14 activerecord/lib/active_record/relation/query_methods.rb
  160. +14 −22 activerecord/lib/active_record/relation/spawn_methods.rb
  161. 0  activerecord/lib/{ → rails}/generators/active_record.rb
  162. +1 −1  activerecord/lib/{ → rails}/generators/active_record/migration/migration_generator.rb
  163. 0  activerecord/lib/{ → rails}/generators/active_record/migration/templates/migration.rb
  164. +1 −1  activerecord/lib/{ → rails}/generators/active_record/model/model_generator.rb
  165. 0  activerecord/lib/{ → rails}/generators/active_record/model/templates/migration.rb
  166. 0  activerecord/lib/{ → rails}/generators/active_record/model/templates/model.rb
  167. +1 −1  activerecord/lib/{ → rails}/generators/active_record/observer/observer_generator.rb
  168. 0  activerecord/lib/{ → rails}/generators/active_record/observer/templates/observer.rb
  169. +1 −1  activerecord/lib/{ → rails}/generators/active_record/session_migration/session_migration_generator.rb
  170. 0  activerecord/lib/{ → rails}/generators/active_record/session_migration/templates/migration.rb
  171. +21 −0 activerecord/test/cases/adapter_test.rb
  172. +1 −1  activerecord/test/cases/associations/eager_test.rb
  173. +9 −5 activerecord/test/cases/associations/has_many_through_associations_test.rb
  174. +0 −9 activerecord/test/cases/associations/has_one_associations_test.rb
  175. +2 −2 activerecord/test/cases/associations/inner_join_association_test.rb
  176. +0 −12 activerecord/test/cases/associations/join_model_test.rb
  177. +8 −0 activerecord/test/cases/associations_test.rb
  178. +9 −9 activerecord/test/cases/base_test.rb
  179. +8 −5 activerecord/test/cases/callbacks_test.rb
  180. +2 −2 activerecord/test/cases/defaults_test.rb
  181. +5 −0 activerecord/test/cases/dirty_test.rb
  182. +16 −5 activerecord/test/cases/finder_test.rb
  183. +6 −6 activerecord/test/cases/fixtures_test.rb
  184. +1 −0  activerecord/test/cases/helper.rb
  185. +2 −0  activerecord/test/cases/json_serialization_test.rb
  186. +0 −40 activerecord/test/cases/lifecycle_test.rb
  187. +5 −5 activerecord/test/cases/log_subscriber_test.rb
  188. +1 −1  activerecord/test/cases/method_scoping_test.rb
  189. +16 −4 activerecord/test/cases/migration_test.rb
  190. +2 −2 activerecord/test/cases/named_scope_test.rb
  191. +4 −0 activerecord/test/cases/query_cache_test.rb
  192. +0 −6 activerecord/test/cases/reflection_test.rb
  193. +9 −0 activerecord/test/cases/schema_authorization_test_postgresql.rb
  194. +32 −6 activerecord/test/cases/transactions_test.rb
  195. +0 −19 activerecord/test/cases/validations/i18n_validation_test.rb
  196. +49 −0 activeresource/lib/active_resource/base.rb
  197. +2 −2 activeresource/lib/active_resource/railtie.rb
  198. +2 −0  activeresource/test/setter_trap.rb
  199. +2 −2 activesupport/activesupport.gemspec
  200. +16 −1 activesupport/lib/active_support/core_ext/array/extract_options.rb
  201. +3 −0  activesupport/lib/active_support/core_ext/class/attribute.rb
  202. +33 −27 activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
  203. +4 −1 activesupport/lib/active_support/core_ext/class/delegating_attributes.rb
  204. +1 −0  activesupport/lib/active_support/core_ext/date_time/conversions.rb
  205. +9 −0 activesupport/lib/active_support/core_ext/hash/conversions.rb
  206. +1 −1  activesupport/lib/active_support/core_ext/kernel/reporting.rb
  207. +3 −1 activesupport/lib/active_support/core_ext/module.rb
  208. +25 −21 activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
  209. +20 −9 activesupport/lib/active_support/core_ext/module/delegation.rb
  210. +8 −8 activesupport/lib/active_support/core_ext/module/introspection.rb
  211. +14 −0 activesupport/lib/active_support/core_ext/module/method_names.rb
  212. +6 −0 activesupport/lib/active_support/core_ext/module/remove_method.rb
  213. +0 −2  activesupport/lib/active_support/core_ext/string/inflections.rb
  214. +10 −3 activesupport/lib/active_support/core_ext/string/output_safety.rb
  215. +1 −0  activesupport/lib/active_support/core_ext/time/conversions.rb
  216. +7 −3 activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb
  217. +4 −0 activesupport/lib/active_support/hash_with_indifferent_access.rb
  218. +2 −2 activesupport/lib/active_support/inflector/transliterate.rb
  219. +2 −2 activesupport/lib/active_support/multibyte.rb
  220. +1 −1  activesupport/lib/active_support/multibyte/utils.rb
  221. +1 −1  activesupport/lib/active_support/notifications/fanout.rb
  222. +2 −4 activesupport/lib/active_support/railtie.rb
  223. +1 −0  activesupport/lib/active_support/ruby/shim.rb
  224. +2 −1  activesupport/lib/active_support/test_case.rb
  225. +2 −2 activesupport/lib/active_support/testing/isolation.rb
  226. +2 −2 activesupport/lib/active_support/values/time_zone.rb
  227. +9 −2 activesupport/test/abstract_unit.rb
  228. +1 −0  activesupport/test/callback_inheritance_test.rb
  229. +1 −1  activesupport/test/callbacks_test.rb
  230. +34 −0 activesupport/test/core_ext/array_ext_test.rb
  231. +7 −1 activesupport/test/core_ext/class/attribute_accessor_test.rb
  232. +14 −8 activesupport/test/core_ext/class/delegating_attributes_test.rb
  233. +3 −1 activesupport/test/core_ext/hash_ext_test.rb
  234. +6 −0 activesupport/test/core_ext/module/attribute_accessor_test.rb
  235. +14 −0 activesupport/test/core_ext/module_test.rb
  236. +5 −1 activesupport/test/core_ext/string_ext_test.rb
  237. +2 −2 activesupport/test/core_ext/time_ext_test.rb
  238. +1 −1  activesupport/test/dependencies_test.rb
  239. +1 −0  activesupport/test/flush_cache_on_private_memoization_test.rb
  240. +4 −12 activesupport/test/inflector_test_cases.rb
  241. +3 −3 activesupport/test/notifications_test.rb
  242. +2 −0  activesupport/test/ts_isolated.rb
  243. +9 −9 ci/ci_build.rb
  244. +7 −1 load_paths.rb
  245. +4 −4 railties/Rakefile
  246. +0 −2  railties/builtin/rails_info/rails/info_helper.rb
  247. BIN  railties/guides/images/challenge.png
  248. BIN  railties/guides/images/edge_badge.png
  249. BIN  railties/guides/images/posts_index.png
  250. BIN  railties/guides/images/rails_welcome.png
  251. +9 −22 railties/guides/rails_guides.rb
  252. +79 −50 railties/guides/rails_guides/generator.rb
  253. +3 −3 railties/guides/rails_guides/textile_extensions.rb
  254. +1 −1  railties/guides/source/2_2_release_notes.textile
  255. +1 −1  railties/guides/source/2_3_release_notes.textile
  256. +42 −34 railties/guides/source/3_0_release_notes.textile
  257. +2 −2 railties/guides/source/action_controller_overview.textile
  258. +1 −1  railties/guides/source/action_mailer_basics.textile
  259. +2 −2 railties/guides/source/action_view_overview.textile
  260. +73 −95 railties/guides/source/active_record_querying.textile
  261. +993 −85 railties/guides/source/active_support_core_extensions.textile
  262. +2 −2 railties/guides/source/activerecord_validations_callbacks.textile
  263. +1 −1  railties/guides/source/caching_with_rails.textile
  264. +61 −59 railties/guides/source/command_line.textile
  265. +2 −2 railties/guides/source/contribute.textile
  266. +14 −7 railties/guides/source/contributing_to_rails.textile
  267. +8 −0 railties/guides/source/credits.textile.erb
  268. +1 −1  railties/guides/source/form_helpers.textile
  269. +628 −494 railties/guides/source/getting_started.textile
  270. +16 −1 railties/guides/source/index.textile.erb
  271. +7 −1 railties/guides/source/layout.html.erb
  272. +299 −71 railties/guides/source/layouts_and_rendering.textile
  273. +12 −10 railties/guides/source/plugins.textile
  274. +119 −117 railties/guides/source/routing.textile
  275. +0 −8 railties/lib/generators/erb.rb
  276. +0 −20 railties/lib/generators/erb/mailer/mailer_generator.rb
  277. +0 −8 railties/lib/generators/test_unit/controller/templates/functional_test.rb
  278. +0 −3  railties/lib/generators/test_unit/mailer/templates/fixture
  279. +3 −0  railties/lib/rails.rb
  280. +39 −1 railties/lib/rails/application.rb
  281. +55 −4 railties/lib/rails/application/configuration.rb
  282. +2 −2 railties/lib/rails/application/finisher.rb
  283. +1 −1  railties/lib/rails/commands.rb
  284. +1 −1  railties/lib/rails/commands/application.rb
  285. +12 −0 railties/lib/rails/commands/dbconsole.rb
  286. +87 −4 railties/lib/rails/engine.rb
  287. +6 −2 railties/lib/rails/generators.rb
  288. +10 −2 railties/lib/rails/generators/base.rb
  289. +21 −0 railties/lib/rails/generators/erb.rb
  290. +4 −5 railties/lib/{ → rails}/generators/erb/controller/controller_generator.rb
  291. 0  railties/lib/{ → rails}/generators/erb/controller/templates/view.html.erb
  292. +13 −0 railties/lib/rails/generators/erb/mailer/mailer_generator.rb
  293. 0  railties/lib/{ → rails}/generators/erb/mailer/templates/view.text.erb
  294. +14 −26 railties/lib/{ → rails}/generators/erb/scaffold/scaffold_generator.rb
  295. 0  railties/lib/{ → rails}/generators/erb/scaffold/templates/_form.html.erb
  296. 0  railties/lib/{ → rails}/generators/erb/scaffold/templates/edit.html.erb
  297. +1 −1  railties/lib/{ → rails}/generators/erb/scaffold/templates/index.html.erb
  298. 0  railties/lib/{ → rails}/generators/erb/scaffold/templates/layout.html.erb
  299. 0  railties/lib/{ → rails}/generators/erb/scaffold/templates/new.html.erb
  300. 0  railties/lib/{ → rails}/generators/erb/scaffold/templates/show.html.erb
Sorry, we could not display the entire diff because too many files (593) changed.
9 Gemfile
View
@@ -7,14 +7,17 @@ gem "rails", "3.0.0.beta1"
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
-if RUBY_VERSION < '1.9'
- gem "ruby-debug", ">= 0.10.3"
+group :mri do
+ if RUBY_VERSION < '1.9'
+ gem "system_timer"
+ gem "ruby-debug", ">= 0.10.3"
+ end
end
# AR
gem "sqlite3-ruby", ">= 1.2.5", :require => 'sqlite3'
-group :test do
+group :db do
gem "pg", ">= 0.9.0"
gem "mysql", ">= 2.8.1"
end
8 Rakefile
View
@@ -49,13 +49,13 @@ end
desc "Install gems for all projects."
task :install => :gem do
- require File.expand_path("../actionpack/lib/action_pack/version", __FILE__)
+ version = File.read("RAILS_VERSION").strip
(PROJECTS - ["railties"]).each do |project|
puts "INSTALLING #{project}"
- system("gem install #{project}/pkg/#{project}-#{ActionPack::VERSION::STRING}.gem --no-ri --no-rdoc")
+ system("gem install #{project}/pkg/#{project}-#{version}.gem --no-ri --no-rdoc")
end
- system("gem install railties/pkg/railties-#{ActionPack::VERSION::STRING}.gem --no-ri --no-rdoc")
- system("gem install pkg/rails-#{ActionPack::VERSION::STRING}.gem --no-ri --no-rdoc")
+ system("gem install railties/pkg/railties-#{version}.gem --no-ri --no-rdoc")
+ system("gem install pkg/rails-#{version}.gem --no-ri --no-rdoc")
end
desc "Generate documentation for the Rails framework"
9 actionmailer/lib/action_mailer/base.rb
View
@@ -1,6 +1,7 @@
require 'mail'
require 'action_mailer/tmail_compat'
require 'action_mailer/collector'
+require 'active_support/core_ext/array/wrap'
module ActionMailer #:nodoc:
# Action Mailer allows you to send email from your application using a mailer model and views.
@@ -590,7 +591,7 @@ def collect_responses_and_parts_order(headers) #:nodoc:
responses, parts_order = [], nil
if block_given?
- collector = ActionMailer::Collector.new(self) { render(action_name) }
+ collector = ActionMailer::Collector.new(lookup_context) { render(action_name) }
yield(collector)
parts_order = collector.responses.map { |r| r[:content_type] }
responses = collector.responses
@@ -604,8 +605,10 @@ def collect_responses_and_parts_order(headers) #:nodoc:
templates_name = headers.delete(:template_name) || action_name
each_template(templates_path, templates_name) do |template|
+ self.formats = template.formats
+
responses << {
- :body => render(:_template => template),
+ :body => render(:template => template),
:content_type => template.mime_type.to_s
}
end
@@ -615,7 +618,7 @@ def collect_responses_and_parts_order(headers) #:nodoc:
end
def each_template(paths, name, &block) #:nodoc:
- Array(paths).each do |path|
+ Array.wrap(paths).each do |path|
templates = lookup_context.find_all(name, path)
templates = templates.uniq_by { |t| t.formats }
12 actionmailer/lib/action_mailer/collector.rb
View
@@ -11,7 +11,6 @@ def initialize(context, &block)
@context = context
@responses = []
@default_render = block
- @default_formats = context.formats
end
def any(*args, &block)
@@ -21,16 +20,11 @@ def any(*args, &block)
end
alias :all :any
- def custom(mime, options={}, &block)
+ def custom(mime, options={})
options.reverse_merge!(:content_type => mime.to_s)
- @context.formats = [mime.to_sym]
- options[:body] = if block
- block.call
- else
- @default_render.call
- end
+ @context.freeze_formats([mime.to_sym])
+ options[:body] = block_given? ? yield : @default_render.call
@responses << options
- @context.formats = @default_formats
end
end
end
6 actionmailer/lib/action_mailer/old_api.rb
View
@@ -31,9 +31,6 @@ module OldApi #:nodoc:
# replies to this message.
adv_attr_accessor :reply_to
- # Specify additional headers to be added to the message.
- adv_attr_accessor :headers
-
# Specify the order in which parts should be sorted, based on content-type.
# This defaults to the value for the +default_implicit_parts_order+.
adv_attr_accessor :implicit_parts_order
@@ -207,7 +204,8 @@ def create_parts
@parts.unshift create_inline_part(@body)
elsif @parts.empty? || @parts.all? { |p| p.content_disposition =~ /^attachment/ }
lookup_context.find_all(@template, @mailer_name).each do |template|
- @parts << create_inline_part(render(:_template => template), template.mime_type)
+ self.formats = template.formats
+ @parts << create_inline_part(render(:template => template), template.mime_type)
end
if @parts.size > 1
4 actionmailer/lib/action_mailer/railtie.rb
View
@@ -3,14 +3,14 @@
module ActionMailer
class Railtie < Rails::Railtie
- railtie_name :action_mailer
+ config.action_mailer = ActiveSupport::OrderedOptions.new
initializer "action_mailer.url_for", :before => :load_environment_config do |app|
ActionMailer.base_hook { include app.routes.url_helpers }
end
require "action_mailer/railties/log_subscriber"
- log_subscriber ActionMailer::Railties::LogSubscriber.new
+ log_subscriber :action_mailer, ActionMailer::Railties::LogSubscriber.new
initializer "action_mailer.logger" do
ActionMailer.base_hook { self.logger ||= Rails.logger }
6 actionmailer/lib/action_mailer/railties/log_subscriber.rb
View
@@ -1,8 +1,10 @@
+require 'active_support/core_ext/array/wrap'
+
module ActionMailer
module Railties
class LogSubscriber < Rails::LogSubscriber
def deliver(event)
- recipients = Array(event.payload[:to]).join(', ')
+ recipients = Array.wrap(event.payload[:to]).join(', ')
info("\nSent mail to #{recipients} (%1.fms)" % event.duration)
debug(event.payload[:mail])
end
@@ -17,4 +19,4 @@ def logger
end
end
end
-end
+end
21 actionmailer/test/abstract_unit.rb
View
@@ -1,4 +1,23 @@
-require File.expand_path('../../../load_paths', __FILE__)
+# Pathname has a warning, so require it first while silencing
+# warnings to shut it up.
+#
+# Also, in 1.9, Bundler creates warnings due to overriding
+# Rubygems methods
+begin
+ old, $VERBOSE = $VERBOSE, nil
+ require 'pathname'
+ require File.expand_path('../../../load_paths', __FILE__)
+ensure
+ $VERBOSE = old
+end
+
+
+require 'active_support/core_ext/kernel/reporting'
+silence_warnings do
+ # These external dependencies have warnings :/
+ require 'text/format'
+ require 'mail'
+end
lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
60 actionmailer/test/base_test.rb
View
@@ -2,6 +2,8 @@
require 'abstract_unit'
class BaseTest < ActiveSupport::TestCase
+ # TODO Add some tests for implicity layout render and url helpers
+ # so we can get rid of old base tests altogether with old base.
class BaseMailer < ActionMailer::Base
self.mailer_name = "base_mailer"
@@ -72,13 +74,20 @@ def explicit_multipart_with_any(hash = {})
end
end
- def custom_block(include_html=false)
+ def explicit_multipart_with_options(include_html = false)
mail do |format|
format.text(:content_transfer_encoding => "base64"){ render "welcome" }
format.html{ render "welcome" } if include_html
end
end
+ def explicit_multipart_with_one_template(hash = {})
+ mail(hash) do |format|
+ format.html
+ format.text
+ end
+ end
+
def implicit_different_template(template_name='')
mail(:template_name => template_name)
end
@@ -146,6 +155,13 @@ def different_layout(layout_name='')
assert_equal("Hello there", email.body.encoded)
end
+ test "should set template content type if mail has only one part" do
+ mail = BaseMailer.html_only
+ assert_equal('text/html', mail.mime_type)
+ mail = BaseMailer.plain_text_only
+ assert_equal('text/plain', mail.mime_type)
+ end
+
# Custom headers
test "custom headers" do
email = BaseMailer.welcome
@@ -160,7 +176,7 @@ def different_layout(layout_name='')
assert_equal('1234@mikel.me.com', mail['In-Reply-To'].decoded)
end
- test "can pass random headers in as a hash" do
+ test "can pass random headers in as a hash to headers" do
hash = {'X-Special-Domain-Specific-Header' => "SecretValue",
'In-Reply-To' => '1234@mikel.me.com' }
mail = BaseMailer.welcome_with_headers(hash)
@@ -364,6 +380,11 @@ def different_layout(layout_name='')
assert_equal("HTML Explicit Multipart", email.parts[1].body.encoded)
end
+ test "explicit multipart have a boundary" do
+ mail = BaseMailer.explicit_multipart
+ assert_not_nil(mail.content_type_parameters[:boundary])
+ end
+
test "explicit multipart does not sort order" do
order = ["text/html", "text/plain"]
with_default BaseMailer, :parts_order => order do
@@ -397,7 +418,7 @@ def different_layout(layout_name='')
assert_equal("TEXT Explicit Multipart Templates", email.parts[1].body.encoded)
end
- test "explicit multipart with any" do
+ test "explicit multipart with format.any" do
email = BaseMailer.explicit_multipart_with_any
assert_equal(2, email.parts.size)
assert_equal("multipart/alternative", email.mime_type)
@@ -407,8 +428,8 @@ def different_layout(layout_name='')
assert_equal("Format with any!", email.parts[1].body.encoded)
end
- test "explicit multipart with options" do
- email = BaseMailer.custom_block(true)
+ test "explicit multipart with format(Hash)" do
+ email = BaseMailer.explicit_multipart_with_options(true)
email.ready_to_send!
assert_equal(2, email.parts.size)
assert_equal("multipart/alternative", email.mime_type)
@@ -418,28 +439,23 @@ def different_layout(layout_name='')
assert_equal("7bit", email.parts[1].content_transfer_encoding)
end
- test "explicit multipart should be multipart" do
- mail = BaseMailer.explicit_multipart
- assert_not_nil(mail.content_type_parameters[:boundary])
- end
-
- test "should set a content type if only has an html part" do
- mail = BaseMailer.html_only
- assert_equal('text/html', mail.mime_type)
- end
-
- test "should set a content type if only has an plain text part" do
- mail = BaseMailer.plain_text_only
- assert_equal('text/plain', mail.mime_type)
- end
-
- test "explicit multipart with one part is rendered as body" do
- email = BaseMailer.custom_block
+ test "explicit multipart with one part is rendered as body and options are merged" do
+ email = BaseMailer.explicit_multipart_with_options
assert_equal(0, email.parts.size)
assert_equal("text/plain", email.mime_type)
assert_equal("base64", email.content_transfer_encoding)
end
+ test "explicit multipart with one template has the expected format" do
+ email = BaseMailer.explicit_multipart_with_one_template
+ assert_equal(2, email.parts.size)
+ assert_equal("multipart/alternative", email.mime_type)
+ assert_equal("text/html", email.parts[0].mime_type)
+ assert_equal("[:html]", email.parts[0].body.encoded)
+ assert_equal("text/plain", email.parts[1].mime_type)
+ assert_equal("[:text]", email.parts[1].body.encoded)
+ end
+
# Class level API with method missing
test "should respond to action methods" do
assert BaseMailer.respond_to?(:welcome)
1  actionmailer/test/fixtures/base_mailer/explicit_multipart_with_one_template.erb
View
@@ -0,0 +1 @@
+<%= self.formats.inspect %>
0  .../test/fixtures/test_mailer/signed_up_with_url.erb → ...t/fixtures/url_test_mailer/signed_up_with_url.erb
View
File renamed without changes
22 actionmailer/test/old_base/mail_layout_test.rb
View
@@ -69,47 +69,25 @@ def test_should_pickup_default_layout
def test_should_pickup_multipart_layout
mail = AutoLayoutMailer.multipart
- # CHANGED: content_type returns an object
- # assert_equal "multipart/alternative", mail.content_type
assert_equal "multipart/alternative", mail.mime_type
assert_equal 2, mail.parts.size
- # CHANGED: content_type returns an object
- # assert_equal 'text/plain', mail.parts.first.content_type
assert_equal 'text/plain', mail.parts.first.mime_type
-
- # CHANGED: body returns an object
- # assert_equal "text/plain layout - text/plain multipart", mail.parts.first.body
assert_equal "text/plain layout - text/plain multipart", mail.parts.first.body.to_s
- # CHANGED: content_type returns an object
- # assert_equal 'text/html', mail.parts.last.content_type
assert_equal 'text/html', mail.parts.last.mime_type
-
- # CHANGED: body returns an object
- # assert_equal "Hello from layout text/html multipart", mail.parts.last.body
assert_equal "Hello from layout text/html multipart", mail.parts.last.body.to_s
end
def test_should_pickup_multipartmixed_layout
mail = AutoLayoutMailer.multipart("multipart/mixed")
- # CHANGED: content_type returns an object
- # assert_equal "multipart/mixed", mail.content_type
assert_equal "multipart/mixed", mail.mime_type
assert_equal 2, mail.parts.size
- # CHANGED: content_type returns an object
- # assert_equal 'text/plain', mail.parts.first.content_type
assert_equal 'text/plain', mail.parts.first.mime_type
- # CHANGED: body returns an object
- # assert_equal "text/plain layout - text/plain multipart", mail.parts.first.body
assert_equal "text/plain layout - text/plain multipart", mail.parts.first.body.to_s
- # CHANGED: content_type returns an object
- # assert_equal 'text/html', mail.parts.last.content_type
assert_equal 'text/html', mail.parts.last.mime_type
- # CHANGED: body returns an object
- # assert_equal "Hello from layout text/html multipart", mail.parts.last.body
assert_equal "Hello from layout text/html multipart", mail.parts.last.body.to_s
end
9 actionmailer/test/old_base/mail_service_test.rb
View
@@ -340,6 +340,8 @@ def setup
@original_logger = TestMailer.logger
@recipient = 'test@localhost'
+
+ TestMailer.delivery_method = :test
end
def teardown
@@ -444,9 +446,6 @@ def test_custom_templating_extension
expected.from = "system@loudthinking.com"
expected.date = Time.local(2004, 12, 12)
- # Stub the render method so no alternative renderers need be present.
- ActionView::Base.any_instance.stubs(:render).returns("Hello there, \n\nMr. #{@recipient}")
-
# Now that the template is registered, there should be one part. The text/plain part.
created = nil
assert_nothing_raised { created = TestMailer.custom_templating_extension(@recipient) }
@@ -1194,6 +1193,6 @@ def test_should_still_raise_exception_with_expected_message_when_calling_an_unde
RespondToMailer.not_a_method
end
- assert_match(/undefined method.*not_a_method/, error.message)
+ assert_match(/method.*not_a_method/, error.message)
end
-end
+end
16 actionmailer/test/old_base/url_test.rb
View
@@ -10,7 +10,7 @@ class ActionMailer::Base
include AppRoutes.url_helpers
end
-class TestMailer < ActionMailer::Base
+class UrlTestMailer < ActionMailer::Base
default_url_options[:host] = 'www.basecamphq.com'
configure do |c|
@@ -26,14 +26,6 @@ def signed_up_with_url(recipient)
@recipient = recipient
@welcome_url = url_for :host => "example.com", :controller => "welcome", :action => "greeting"
end
-
- class <<self
- attr_accessor :received_body
- end
-
- def receive(mail)
- self.class.received_body = mail.body
- end
end
class ActionMailerUrlTest < Test::Unit::TestCase
@@ -65,7 +57,7 @@ def teardown
end
def test_signed_up_with_url
- TestMailer.delivery_method = :test
+ UrlTestMailer.delivery_method = :test
AppRoutes.draw do |map|
map.connect ':controller/:action/:id'
@@ -80,14 +72,14 @@ def test_signed_up_with_url
expected.date = Time.local(2004, 12, 12)
created = nil
- assert_nothing_raised { created = TestMailer.signed_up_with_url(@recipient) }
+ assert_nothing_raised { created = UrlTestMailer.signed_up_with_url(@recipient) }
assert_not_nil created
expected.message_id = '<123@456>'
created.message_id = '<123@456>'
assert_equal expected.encoded, created.encoded
- assert_nothing_raised { TestMailer.signed_up_with_url(@recipient).deliver }
+ assert_nothing_raised { UrlTestMailer.signed_up_with_url(@recipient).deliver }
assert_not_nil ActionMailer::Base.deliveries.first
delivered = ActionMailer::Base.deliveries.first
1  actionpack/lib/abstract_controller.rb
View
@@ -12,6 +12,7 @@
module AbstractController
extend ActiveSupport::Autoload
+ autoload :Assigns
autoload :Base
autoload :Callbacks
autoload :Collector
21 actionpack/lib/abstract_controller/assigns.rb
View
@@ -0,0 +1,21 @@
+module AbstractController
+ module Assigns
+ # This method should return a hash with assigns.
+ # You can overwrite this configuration per controller.
+ # :api: public
+ def view_assigns
+ hash = {}
+ variables = instance_variable_names
+ variables -= protected_instance_variables if respond_to?(:protected_instance_variables)
+ variables.each { |name| hash[name] = instance_variable_get(name) }
+ hash
+ end
+
+ # This method assigns the hash specified in _assigns_hash to the given object.
+ # :api: private
+ # TODO Ideally, this should be done on AV::Base.new initialization.
+ def _evaluate_assigns(object)
+ view_assigns.each { |k,v| object.instance_variable_set(k, v) }
+ end
+ end
+end
10 actionpack/lib/abstract_controller/helpers.rb
View
@@ -6,16 +6,10 @@ module Helpers
include Rendering
- def self.next_serial
- @helper_serial ||= 0
- @helper_serial += 1
- end
-
included do
- class_attribute :_helpers, :_helper_serial
+ class_attribute :_helpers
delegate :_helpers, :to => :'self.class'
self._helpers = Module.new
- self._helper_serial = ::AbstractController::Helpers.next_serial
end
module ClassMethods
@@ -95,8 +89,6 @@ def #{meth}(*args, &blk)
# helper(:three, BlindHelper) { def mice() 'mice' end }
#
def helper(*args, &block)
- self._helper_serial = AbstractController::Helpers.next_serial + 1
-
modules_for_helpers(args).each do |mod|
add_template_helper(mod)
end
27 actionpack/lib/abstract_controller/layouts.rb
View
@@ -1,3 +1,5 @@
+require "active_support/core_ext/module/remove_method"
+
module AbstractController
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
# repeated setups. The inclusion pattern has pages that look like this:
@@ -182,7 +184,9 @@ module LayoutConditions
#
# ==== Returns
# Boolean:: True if the action has a layout, false otherwise.
- def _action_has_layout?
+ def action_has_layout?
+ return unless super
+
conditions = _layout_conditions
if only = conditions[:only]
@@ -237,6 +241,8 @@ def _implied_layout_name
# name, return that string. Otherwise, use the superclass'
# layout (which might also be implied)
def _write_layout_method
+ remove_possible_method(:_layout)
+
case defined?(@_layout) ? @_layout : nil
when String
self.class_eval %{def _layout; #{@_layout.inspect} end}
@@ -287,6 +293,17 @@ def _normalize_options(options)
end
end
+ attr_writer :action_has_layout
+
+ def initialize(*)
+ @action_has_layout = true
+ super
+ end
+
+ def action_has_layout?
+ @action_has_layout
+ end
+
private
# This will be overwritten by _write_layout_method
@@ -326,13 +343,13 @@ def _layout_for_option(name)
# Template:: The template object for the default layout (or nil)
def _default_layout(require_layout = false)
begin
- layout_name = _layout if _action_has_layout?
+ layout_name = _layout if action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
- if require_layout && _action_has_layout? && !layout_name
+ if require_layout && action_has_layout? && !layout_name
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
@@ -343,9 +360,5 @@ def _default_layout(require_layout = false)
def _include_layout?(options)
(options.keys & [:text, :inline, :partial]).empty? || options.key?(:layout)
end
-
- def _action_has_layout?
- true
- end
end
end
76 actionpack/lib/abstract_controller/rendering.rb
View
@@ -31,6 +31,7 @@ def locale=(value)
module Rendering
extend ActiveSupport::Concern
+
include AbstractController::ViewPaths
# Overwrite process to setup I18n proxy.
@@ -41,21 +42,52 @@ def process(*) #:nodoc:
I18n.config = old_config
end
+ module ClassMethods
+ def view_context_class
+ @view_context_class ||= begin
+ controller = self
+ Class.new(ActionView::Base) do
+ if controller.respond_to?(:_helpers)
+ include controller._helpers
+
+ if controller.respond_to?(:_router)
+ include controller._router.url_helpers
+ end
+
+ # TODO: Fix RJS to not require this
+ self.helpers = controller._helpers
+ end
+ end
+ end
+ end
+ end
+
+ attr_writer :view_context_class
+
+ def view_context_class
+ @view_context_class || self.class.view_context_class
+ end
+
+ def initialize(*)
+ @view_context_class = nil
+ super
+ end
+
# An instance of a view class. The default view class is ActionView::Base
#
# The view class must have the following methods:
- # View.for_controller[controller]
+ # View.new[lookup_context, assigns, controller]
# Create a new ActionView instance for a controller
- # View#render_template[options]
+ # View#render[options]
# Returns String with the rendered template
#
# Override this method in a module to change the default behavior.
def view_context
- @_view_context ||= ActionView::Base.for_controller(self)
+ view_context_class.new(lookup_context, view_assigns, self)
end
- # Mostly abstracts the fact that calling render twice is a DoubleRenderError.
- # Delegates render_to_body and sticks the result in self.response_body.
+ # Normalize arguments, options and then delegates render_to_body and
+ # sticks the result in self.response_body.
def render(*args, &block)
options = _normalize_args(*args, &block)
_normalize_options(options)
@@ -74,12 +106,13 @@ def render_to_body(options = {})
# :api: plugin
def render_to_string(options={})
_normalize_options(options)
- AbstractController::Rendering.body_to_s(render_to_body(options))
+ render_to_body(options)
end
# Find and renders a template based on the options given.
- def _render_template(options)
- view_context.render_template(options) { |template| _with_template_hook(template) }
+ # :api: private
+ def _render_template(options) #:nodoc:
+ view_context.render(options)
end
# The prefix used in render "foo" shortcuts.
@@ -87,20 +120,19 @@ def _prefix
controller_path
end
- # Return a string representation of a Rack-compatible response body.
- def self.body_to_s(body)
- if body.respond_to?(:to_str)
- body
- else
- strings = []
- body.each { |part| strings << part.to_s }
- body.close if body.respond_to?(:close)
- strings.join
- end
- end
-
private
+ # This method should return a hash with assigns.
+ # You can overwrite this configuration per controller.
+ # :api: public
+ def view_assigns
+ hash = {}
+ variables = instance_variable_names
+ variables -= protected_instance_variables if respond_to?(:protected_instance_variables)
+ variables.each { |name| hash[name.to_s[1..-1]] = instance_variable_get(name) }
+ hash
+ end
+
# Normalize options by converting render "foo" to render :action => "foo" and
# render "foo/bar" to render :file => "foo/bar".
def _normalize_args(action=nil, options={})
@@ -134,9 +166,5 @@ def _normalize_options(options)
def _process_options(options)
end
-
- def _with_template_hook(template)
- self.formats = template.formats
- end
end
end
6 actionpack/lib/abstract_controller/view_paths.rb
View
@@ -7,7 +7,7 @@ module ViewPaths
self._view_paths = ActionView::PathSet.new
end
- delegate :template_exists?, :view_paths, :formats, :formats=,
+ delegate :find_template, :template_exists?, :view_paths, :formats, :formats=,
:locale, :locale=, :to => :lookup_context
# LookupContext is the object responsible to hold all information required to lookup
@@ -29,10 +29,6 @@ def prepend_view_path(path)
lookup_context.view_paths.unshift(*path)
end
- def template_exists?(*args)
- lookup_context.exists?(*args)
- end
-
module ClassMethods
# Append a path to the list of view paths for this controller.
#
9 actionpack/lib/action_controller/base.rb
View
@@ -2,7 +2,6 @@ module ActionController
class Base < Metal
abstract!
- include AbstractController::Callbacks
include AbstractController::Layouts
include AbstractController::Translation
@@ -20,9 +19,11 @@ class Base < Metal
include SessionManagement
include ActionController::Caching
include ActionController::MimeResponds
+ include ActionController::PolymorphicRoutes
# Rails 2.x compatibility
include ActionController::Compatibility
+ include ActionController::ImplicitRender
include ActionController::Cookies
include ActionController::Flash
@@ -36,8 +37,12 @@ class Base < Metal
# Add instrumentations hooks at the bottom, to ensure they instrument
# all the methods properly.
include ActionController::Instrumentation
- include ImplicitRender
+ # Before callbacks should also be executed the earliest as possible, so
+ # also include them at the bottom.
+ include AbstractController::Callbacks
+
+ # The same with rescue, append it at the end to wrap as much as possible.
include ActionController::Rescue
def self.inherited(klass)
28 actionpack/lib/action_controller/caching/actions.rb
View
@@ -80,6 +80,7 @@ module ClassMethods
def caches_action(*actions)
return unless cache_configured?
options = actions.extract_options!
+ options[:layout] = true unless options.key?(:layout)
filter_options = options.extract!(:if, :unless).merge(:only => actions)
cache_options = options.extract!(:layout, :cache_path).merge(:store_options => options)
@@ -87,14 +88,12 @@ def caches_action(*actions)
end
end
- def _render_cache_fragment(cache, extension, layout)
- render :text => cache, :layout => layout, :content_type => Mime[extension || :html]
- end
-
- def _save_fragment(name, layout, options)
+ def _save_fragment(name, options)
return unless caching_allowed?
- content = layout ? view_context.content_for(:layout) : response_body
+ content = response_body
+ content = content.join if content.is_a?(Array)
+
write_fragment(name, content, options)
end
@@ -112,7 +111,7 @@ def expire_action(options = {})
class ActionCacheFilter #:nodoc:
def initialize(options, &block)
- @cache_path, @store_options, @layout =
+ @cache_path, @store_options, @cache_layout =
options.values_at(:cache_path, :store_options, :layout)
end
@@ -125,12 +124,19 @@ def filter(controller)
cache_path = ActionCachePath.new(controller, path_options || {})
- if cache = controller.read_fragment(cache_path.path, @store_options)
- controller._render_cache_fragment(cache, cache_path.extension, @layout == false)
- else
+ body = controller.read_fragment(cache_path.path, @store_options)
+
+ unless body
+ controller.action_has_layout = false unless @cache_layout
yield
- controller._save_fragment(cache_path.path, @layout == false, @store_options)
+ controller.action_has_layout = true
+ body = controller._save_fragment(cache_path.path, @store_options)
end
+
+ body = controller.render_to_string(:text => cache, :layout => true) unless @cache_layout
+
+ controller.response_body = body
+ controller.content_type = Mime[cache_path.extension || :html]
end
end
22 actionpack/lib/action_controller/caching/fragments.rb
View
@@ -34,26 +34,13 @@ def fragment_cache_key(key)
ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
end
- def fragment_for(buffer, name = {}, options = nil, &block) #:nodoc:
- if perform_caching
- if fragment_exist?(name, options)
- buffer.safe_concat(read_fragment(name, options))
- else
- pos = buffer.length
- block.call
- write_fragment(name, buffer[pos..-1], options)
- end
- else
- block.call
- end
- end
-
# Writes <tt>content</tt> to the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
def write_fragment(key, content, options = nil)
return content unless cache_configured?
- key = fragment_cache_key(key)
+ key = fragment_cache_key(key)
instrument_fragment_cache :write_fragment, key do
+ content = content.html_safe.to_str if content.respond_to?(:html_safe)
cache_store.write(key, content, options)
end
content
@@ -62,10 +49,11 @@ def write_fragment(key, content, options = nil)
# Reads a cached fragment from the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
def read_fragment(key, options = nil)
return unless cache_configured?
- key = fragment_cache_key(key)
+ key = fragment_cache_key(key)
instrument_fragment_cache :read_fragment, key do
- cache_store.read(key, options)
+ result = cache_store.read(key, options)
+ result.respond_to?(:html_safe) ? result.html_safe : result
end
end
2  actionpack/lib/action_controller/deprecated/base.rb
View
@@ -63,7 +63,7 @@ def ip_spoofing_check=(value)
def ip_spoofing_check
ActiveSupport::Deprecation.warn "ActionController::Base.ip_spoofing_check is deprecated. " <<
"Configuring ip_spoofing_check on the application configures a middleware.", caller
- Rails.application.config.action_disaptch.ip_spoofing_check
+ Rails.application.config.action_dispatch.ip_spoofing_check
end
def trusted_proxies=(value)
14 actionpack/lib/action_controller/metal.rb
View
@@ -34,11 +34,12 @@ def controller_name
# and response object available. You might wish to control the
# environment and response manually for performance reasons.
- attr_internal :status, :headers, :content_type, :response, :request
+ attr_internal :headers, :response, :request
delegate :session, :to => "@_request"
def initialize(*)
- @_headers = {}
+ @_headers = {"Content-Type" => "text/html"}
+ @_status = 200
super
end
@@ -62,10 +63,19 @@ def location=(url)
headers["Location"] = url
end
+ def status
+ @_status
+ end
+
def status=(status)
@_status = Rack::Utils.status_code(status)
end
+ def response_body=(val)
+ body = val.respond_to?(:each) ? val : [val]
+ super body
+ end
+
# :api: private
def dispatch(name, request)
@_request = request
9 actionpack/lib/action_controller/metal/compatibility.rb
View
@@ -40,15 +40,6 @@ def rescue_action(env)
def initialize_template_class(*) end
def assign_shortcuts(*) end
- def template
- @template ||= view_context
- end
-
- def process_action(*)
- template
- super
- end
-
def _normalize_options(options)
if options[:action] && options[:action].to_s.include?(?/)
ActiveSupport::Deprecation.warn "Giving a path to render :action is deprecated. " <<
3  actionpack/lib/action_controller/metal/mime_responds.rb
View
@@ -261,7 +261,8 @@ def retrieve_response_from_mimes(mimes=nil, &block)
block.call(collector) if block_given?
if format = request.negotiate_mime(collector.order)
- self.formats = [format.to_sym]
+ self.content_type ||= format.to_s
+ lookup_context.freeze_formats([format.to_sym])
collector.response_for(format)
else
head :not_acceptable
6 actionpack/lib/action_controller/metal/rack_delegation.rb
View
@@ -5,10 +5,8 @@ module ActionController
module RackDelegation
extend ActiveSupport::Concern
- included do
- delegate :headers, :status=, :location=, :content_type=,
- :status, :location, :content_type, :to => "@_response"
- end
+ delegate :headers, :status=, :location=, :content_type=,
+ :status, :location, :content_type, :to => "@_response"
def dispatch(action, request)
@_response = ActionDispatch::Response.new
2  actionpack/lib/action_controller/metal/redirecting.rb
View
@@ -76,7 +76,7 @@ def _compute_redirect_to_location(options)
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
- when %r{^\w[\w\d+.-]*:.*}
+ when %r{^\w[\w+.-]*:.*}
options
when String
request.protocol + request.host_with_port + options
3  actionpack/lib/action_controller/metal/renderers.rb
View
@@ -87,8 +87,9 @@ def self._write_render_options
end
add :update do |proc, options|
+ view_context = self.view_context
generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(view_context, &proc)
- self.content_type = Mime::JS
+ self.content_type = Mime::JS
self.response_body = generator.to_s
end
end
21 actionpack/lib/action_controller/metal/rendering.rb
View
@@ -5,26 +5,31 @@ module Rendering
include ActionController::RackDelegation
include AbstractController::Rendering
- def process(*)
+ # Before processing, set the request formats in current controller formats.
+ def process_action(*) #:nodoc:
self.formats = request.formats.map { |x| x.to_sym }
super
end
- def render(*args)
+ # Check for double render errors and set the content_type after rendering.
+ def render(*args) #:nodoc:
raise ::AbstractController::DoubleRenderError if response_body
super
+ self.content_type ||= Mime[formats.first].to_s
response_body
end
private
- def _normalize_args(action=nil, options={}, &blk)
+ # Normalize arguments by catching blocks and setting them on :update.
+ def _normalize_args(action=nil, options={}, &blk) #:nodoc:
options = super
options[:update] = blk if block_given?
options
end
- def _normalize_options(options)
+ # Normalize both text and status options.
+ def _normalize_options(options) #:nodoc:
if options.key?(:text) && options[:text].respond_to?(:to_text)
options[:text] = options[:text].to_text
end
@@ -36,7 +41,8 @@ def _normalize_options(options)
super
end
- def _process_options(options)
+ # Process controller specific options, as status, content-type and location.
+ def _process_options(options) #:nodoc:
status, content_type, location = options.values_at(:status, :content_type, :location)
self.status = status if status
@@ -46,10 +52,5 @@ def _process_options(options)
super
end
- def _with_template_hook(template)
- super
- self.content_type ||= template.mime_type.to_s
- end
-
end
end
2  actionpack/lib/action_controller/metal/request_forgery_protection.rb
View
@@ -12,7 +12,7 @@ module RequestForgeryProtection
included do
# Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
# sets it to <tt>:authenticity_token</tt> by default.
- config.request_forgery_protection_token ||= true
+ config.request_forgery_protection_token ||= :authenticity_token
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
config.allow_forgery_protection ||= true
2  actionpack/lib/action_controller/metal/responder.rb
View
@@ -1,3 +1,5 @@
+require 'active_support/json'
+
module ActionController #:nodoc:
# Responder is responsible for exposing a resource to different mime requests,
# usually depending on the HTTP verb. The responder is triggered when
17 actionpack/lib/action_controller/railtie.rb
View
@@ -1,16 +1,17 @@
require "rails"
require "action_controller"
+require "action_dispatch/railtie"
require "action_view/railtie"
require "active_support/core_ext/class/subclasses"
require "active_support/deprecation/proxy_wrappers"
require "active_support/deprecation"
+require "action_controller/railties/log_subscriber"
+require "action_controller/railties/url_helpers"
+
module ActionController
class Railtie < Rails::Railtie
- railtie_name :action_controller
-
- require "action_controller/railties/log_subscriber"
- require "action_controller/railties/url_helpers"
+ config.action_controller = ActiveSupport::OrderedOptions.new
ad = config.action_dispatch
config.action_controller.singleton_class.send(:define_method, :session) do
@@ -37,7 +38,7 @@ class Railtie < Rails::Railtie
ad.session_store = val
end
- log_subscriber ActionController::Railties::LogSubscriber.new
+ log_subscriber :action_controller, ActionController::Railties::LogSubscriber.new
initializer "action_controller.logger" do
ActionController.base_hook { self.logger ||= Rails.logger }
@@ -52,7 +53,9 @@ class Railtie < Rails::Railtie
ac.stylesheets_dir = paths.public.stylesheets.to_a.first
ac.secret = app.config.cookie_secret
- ActionController.base_hook { self.config.replace(ac) }
+ ActionController.base_hook do
+ self.config.merge!(ac)
+ end
end
initializer "action_controller.initialize_framework_caches" do
@@ -67,7 +70,7 @@ class Railtie < Rails::Railtie
initializer "action_controller.url_helpers" do |app|
ActionController.base_hook do
- extend ::ActionController::Railtie::UrlHelpers.with(app.routes)
+ extend ::ActionController::Railties::UrlHelpers.with(app.routes)
end
message = "ActionController::Routing::Routes is deprecated. " \
2  actionpack/lib/action_controller/railties/url_helpers.rb
View
@@ -1,5 +1,5 @@
module ActionController
- class Railtie
+ module Railties
module UrlHelpers
def self.with(router)
Module.new do
103 actionpack/lib/action_controller/test_case.rb
View
@@ -1,7 +1,107 @@
require 'rack/session/abstract/id'
-require 'action_view/test_case'
module ActionController
+ module TemplateAssertions
+ extend ActiveSupport::Concern
+
+ included do
+ setup :setup_subscriptions
+ teardown :teardown_subscriptions
+ end
+
+ def setup_subscriptions
+ @partials = Hash.new(0)
+ @templates = Hash.new(0)
+ @layouts = Hash.new(0)
+
+ ActiveSupport::Notifications.subscribe("action_view.render_template") do |name, start, finish, id, payload|
+ path = payload[:layout]
+ @layouts[path] += 1
+ end
+
+ ActiveSupport::Notifications.subscribe("action_view.render_template!") do |name, start, finish, id, payload|
+ path = payload[:virtual_path]
+ next unless path
+ partial = path =~ /^.*\/_[^\/]*$/
+ if partial
+ @partials[path] += 1
+ @partials[path.split("/").last] += 1
+ @templates[path] += 1
+ else
+ @templates[path] += 1
+ end
+ end
+ end
+
+ def teardown_subscriptions
+ ActiveSupport::Notifications.unsubscribe("action_view.render_template!")
+ end
+
+ # Asserts that the request was rendered with the appropriate template file or partials
+ #
+ # ==== Examples
+ #
+ # # assert that the "new" view template was rendered
+ # assert_template "new"
+ #
+ # # assert that the "_customer" partial was rendered twice
+ # assert_template :partial => '_customer', :count => 2
+ #
+ # # assert that no partials were rendered
+ # assert_template :partial => false
+ #
+ def assert_template(options = {}, message = nil)
+ validate_request!
+
+ case options
+ when NilClass, String
+ rendered = @templates
+ msg = build_message(message,
+ "expecting <?> but rendering with <?>",
+ options, rendered.keys.join(', '))
+ assert_block(msg) do
+ if options.nil?
+ @templates.blank?
+ else
+ rendered.any? { |t,num| t.match(options) }
+ end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ if expected_count = options[:count]
+ actual_count = @partials[expected_partial]
+ # actual_count = found.nil? ? 0 : found[1]
+ msg = build_message(message,
+ "expecting ? to be rendered ? time(s) but rendered ? time(s)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ elsif options.key?(:layout)
+ msg = build_message(message,
+ "expecting layout <?> but action rendered <?>",
+ expected_layout, @layouts.keys)
+
+ case layout = options[:layout]
+ when String
+ assert(@layouts.include?(expected_layout), msg)
+ when Regexp
+ assert(@layouts.any? {|l| l =~ layout }, msg)
+ when nil
+ assert(@layouts.empty?, msg)
+ end
+ else
+ msg = build_message(message,
+ "expecting partial <?> but action rendered <?>",
+ options[:partial], @partials.keys)
+ assert(@partials.include?(expected_partial), msg)
+ end
+ else
+ assert @partials.empty?,
+ "Expected no partials to be rendered"
+ end
+ end
+ end
+ end
+
class TestRequest < ActionDispatch::TestRequest #:nodoc:
def initialize(env = {})
super
@@ -181,6 +281,7 @@ def initialize(session = {})
# assert_redirected_to page_url(:title => 'foo')
class TestCase < ActiveSupport::TestCase
include ActionDispatch::TestProcess
+ include ActionController::TemplateAssertions
# Executes a request simulating GET HTTP method and set/volley the response
def get(action, parameters = nil, session = nil, flash = nil)
1  actionpack/lib/action_dispatch/http/filter_parameters.rb
View
@@ -25,7 +25,6 @@ module Http
module FilterParameters
extend ActiveSupport::Concern
- mattr_reader :compiled_parameter_filter_for
@@compiled_parameter_filter_for = {}
# Return a hash of parameters with all sensitive data replaced.
8 actionpack/lib/action_dispatch/http/mime_type.rb
View
@@ -52,12 +52,6 @@ class Type
cattr_reader :browser_generated_types
attr_reader :symbol
- @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
- def self.unverifiable_types
- ActiveSupport::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller)
- @@unverifiable_types
- end
-
# A simple helper class used in parsing the accept header
class AcceptItem #:nodoc:
attr_accessor :order, :name, :q
@@ -100,7 +94,7 @@ def register_alias(string, symbol, extension_synonyms = [])
end
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
- Mime.instance_eval { const_set symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms) }
+ Mime.const_set(symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms))
SET << Mime.const_get(symbol.to_s.upcase)
1  actionpack/lib/action_dispatch/middleware/cookies.rb
View
@@ -84,6 +84,7 @@ def []=(key, options)
options[:path] ||= "/"
@set_cookies[key] = options
+ @delete_cookies.delete(key)
value
end
14 actionpack/lib/action_dispatch/middleware/show_exceptions.rb
View
@@ -5,20 +5,6 @@
module ActionDispatch
# This middleware rescues any exception returned by the application and renders
# nice exception pages if it's being rescued locally.
- #
- # Every time an exception is caught, a notification is published, becoming a good API
- # to deal with exceptions. So, if you want send an e-mail through ActionMailer
- # everytime this notification is published, you just need to do the following:
- #
- # ActiveSupport::Notifications.subscribe "action_dispatch.show_exception" do |name, start, end, instrumentation_id, payload|
- # ExceptionNotifier.deliver_exception(start, payload)
- # end
- #
- # The payload is a hash which has two pairs:
- #
- # * :env - Contains the rack env for the given request;
- # * :exception - The exception raised;
- #
class ShowExceptions
LOCALHOST = ['127.0.0.1', '::1'].freeze
5 actionpack/lib/action_dispatch/railtie.rb
View
@@ -3,9 +3,8 @@
module ActionDispatch
class Railtie < Rails::Railtie
- railtie_name :action_dispatch
-
- config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ config.action_dispatch = ActiveSupport::OrderedOptions.new
+ config.action_dispatch.x_sendfile_header = ""
config.action_dispatch.ip_spoofing_check = true
# Prepare dispatcher callbacks and run 'prepare' callbacks
1  actionpack/lib/action_dispatch/routing.rb
View
@@ -1,5 +1,6 @@
require 'active_support/core_ext/object/to_param'
require 'active_support/core_ext/regexp'
+require 'action_controller/polymorphic_routes'
module ActionDispatch
# == Routing
69 actionpack/lib/action_dispatch/routing/mapper.rb
View
@@ -32,6 +32,8 @@ def call(env)
end
class Mapping
+ IGNORE_OPTIONS = [:to, :as, :controller, :action, :via, :on, :constraints, :defaults, :only, :except, :anchor]
+
def initialize(set, scope, args)
@set, @scope = set, scope
@path, @options = extract_path_and_options(args)
@@ -45,18 +47,21 @@ def to_route
def extract_path_and_options(args)
options = args.extract_options!
- case
- when using_to_shorthand?(args, options)
+ if using_to_shorthand?(args, options)
path, to = options.find { |name, value| name.is_a?(String) }
options.merge!(:to => to).delete(path) if path
- when using_match_shorthand?(args, options)
- path = args.first
- options = { :to => path.gsub("/", "#"), :as => path.gsub("/", "_") }
else
path = args.first
end
- [ normalize_path(path), options ]
+ path = normalize_path(path)
+
+ if using_match_shorthand?(path, options)
+ options[:to] ||= path[1..-1].sub(%r{/([^/]*)$}, '#\1')
+ options[:as] ||= path[1..-1].gsub("/", "_")
+ end
+
+ [ path, options ]
end
# match "account" => "account#index"
@@ -65,14 +70,13 @@ def using_to_shorthand?(args, options)
end
# match "account/overview"
- def using_match_shorthand?(args, options)
- args.present? && options.except(:via, :anchor).empty? && !args.first.include?(':')
+ def using_match_shorthand?(path, options)
+ path && options.except(:via, :anchor, :to, :as).empty? && path =~ %r{^/[\w\/]+$}
end
def normalize_path(path)
- path = "#{@scope[:path]}/#{path}"
- raise ArgumentError, "path is required" if path.empty?
- Mapper.normalize_path(path)
+ raise ArgumentError, "path is required" if @scope[:path].blank? && path.blank?
+ Mapper.normalize_path("#{@scope[:path]}/#{path}")
end
def app
@@ -94,7 +98,15 @@ def requirements
end
def defaults
- @defaults ||= if to.respond_to?(:call)
+ @defaults ||= (@options[:defaults] || {}).tap do |defaults|
+ defaults.merge!(default_controller_and_action)
+ defaults.reverse_merge!(@scope[:defaults]) if @scope[:defaults]
+ @options.each { |k, v| defaults[k] = v unless v.is_a?(Regexp) || IGNORE_OPTIONS.include?(k.to_sym) }
+ end
+ end
+
+ def default_controller_and_action
+ if to.respond_to?(:call)
{ }
else
defaults = case to
@@ -144,8 +156,8 @@ def request_method_condition
def segment_keys
@segment_keys ||= Rack::Mount::RegexpWithNamedGroups.new(
- Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS)
- ).names
+ Rack::Mount::Strexp.compile(@path, requirements, SEPARATORS)
+ ).names
end
def to
@@ -297,11 +309,14 @@ def constraints(constraints = {})
scope(:constraints => constraints) { yield }
end
+ def defaults(defaults = {})
+ scope(:defaults => defaults) { yield }
+ end
+
def match(*args)
options = args.extract_options!
options = (@scope[:options] || {}).merge(options)
- options[:anchor] = true unless options.key?(:anchor)
if @scope[:name_prefix] && !options[:as].blank?
options[:as] = "#{@scope[:name_prefix]}_#{options[:as]}"
@@ -342,6 +357,10 @@ def merge_constraints_scope(parent, child)
merge_options_scope(parent, child)
end
+ def merge_defaults_scope(parent, child)
+ merge_options_scope(parent, child)
+ end
+
def merge_blocks_scope(parent, child)
(parent || []) + [child]
end
@@ -362,11 +381,11 @@ def self.default_actions
attr_reader :plural, :singular, :options
def initialize(entities, options = {})
- entities = entities.to_s
+ @name = entities.to_s
@options = options
- @plural = entities.pluralize
- @singular = entities.singularize
+ @plural = @name.pluralize
+ @singular = @name.singularize
end
def default_actions
@@ -393,7 +412,7 @@ def action_type(action)
end
def name
- options[:as] || plural
+ options[:as] || @name
end
def controller
@@ -438,8 +457,8 @@ def action_type(action)
end
end
- def name
- options[:as] || singular
+ def member_name
+ name
end
end
@@ -460,7 +479,7 @@ def resource(*resources, &block)
scope(:path => resource.name.to_s, :controller => resource.controller) do
with_scope_level(:resource, resource) do
- scope(:name_prefix => resource.name.to_s) do
+ scope(:name_prefix => resource.name.to_s, :as => "") do
yield if block_given?
end
@@ -468,8 +487,8 @@ def resource(*resources, &block)
post :create if resource.actions.include?(:create)
put :update if resource.actions.include?(:update)
delete :destroy if resource.actions.include?(:destroy)
- get :new, :as => resource.singular if resource.actions.include?(:new)
- get :edit, :as => resource.singular if resource.actions.include?(:edit)
+ get :new, :as => resource.name if resource.actions.include?(:new)
+ get :edit, :as => resource.name if resource.actions.include?(:edit)
end
end
@@ -563,6 +582,8 @@ def mount(app, options = nil)
def match(*args)
options = args.extract_options!
+ options[:anchor] = true unless options.key?(:anchor)
+
if args.length > 1
args.each { |path| match(path, options) }
return self
26 actionpack/lib/action_dispatch/routing/route_set.rb
View
@@ -65,7 +65,7 @@ def split_glob_param!(params)
# named routes.
class NamedRouteCollection #:nodoc:
include Enumerable
- attr_reader :routes, :helpers
+ attr_reader :routes, :helpers, :module
def initialize
clear!
@@ -179,6 +179,7 @@ def #{selector}(*args)
url_for(options)
end
+ protected :#{selector}
END_EVAL
helpers << selector
end
@@ -219,14 +220,16 @@ def draw(&block)
end
def finalize!
+ return if @finalized
+ @finalized = true
@set.add_route(NotFound)
- install_helpers
@set.freeze
end
def clear!
# Clear the controller cache so we may discover new ones
@controller_constraints = nil
+ @finalized = false
routes.clear
named_routes.clear
@set = ::Rack::Mount::RouteSet.new(:parameters_key => PARAMETERS_KEY)
@@ -239,21 +242,30 @@ def install_helpers(destinations = [ActionController::Base, ActionView::Base], r
def url_helpers
@url_helpers ||= begin
- router = self
+ routes = self
- Module.new do
+ helpers = Module.new do
extend ActiveSupport::Concern
include UrlFor
+ @routes = routes
+ class << self
+ delegate :url_for, :to => '@routes'
+ end
+ extend routes.named_routes.module
+
# ROUTES TODO: install_helpers isn't great... can we make a module with the stuff that
# we can include?
# Yes plz - JP
included do
- router.install_helpers(self)
+ routes.install_helpers(self)
+ singleton_class.send(:define_method, :_router) { routes }
end
- define_method(:_router) { router }
+ define_method(:_router) { routes }
end
+
+ helpers
end
end
@@ -406,6 +418,7 @@ def generate(options, recall = {}, extras = false)
RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash]