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 into rails

  • Loading branch information...
commit 2107921000f4a186fed36e676d1ac089c8be1f99 2 parents ccb7d9d + ed8501e
@mikel mikel authored
Showing with 6,400 additions and 2,813 deletions.
  1. +38 −5 actionmailer/lib/action_mailer/base.rb
  2. +16 −22 actionmailer/lib/action_mailer/deprecated_body.rb
  3. +4 −6 actionmailer/test/mail_service_test.rb
  4. +74 −66 actionpack/lib/abstract_controller/base.rb
  5. +1 −1  actionpack/lib/abstract_controller/rendering.rb
  6. +1 −4 actionpack/lib/action_controller/deprecated/dispatcher.rb
  7. +3 −183 actionpack/lib/action_controller/metal/cookies.rb
  8. +0 −4 actionpack/lib/action_controller/metal/instrumentation.rb
  9. +17 −17 actionpack/lib/action_controller/metal/responder.rb
  10. +3 −0  actionpack/lib/action_controller/metal/testing.rb
  11. +0 −50 actionpack/lib/action_controller/railtie.rb
  12. +1 −6 actionpack/lib/action_controller/railties/subscriber.rb
  13. +11 −1 actionpack/lib/action_dispatch.rb
  14. +123 −0 actionpack/lib/action_dispatch/http/cache.rb
  15. +101 −0 actionpack/lib/action_dispatch/http/mime_negotiation.rb
  16. +50 −0 actionpack/lib/action_dispatch/http/parameters.rb
  17. +27 −352 actionpack/lib/action_dispatch/http/request.rb
  18. +3 −79 actionpack/lib/action_dispatch/http/response.rb
  19. +48 −0 actionpack/lib/action_dispatch/http/upload.rb
  20. +129 −0 actionpack/lib/action_dispatch/http/url.rb
  21. +0 −2  actionpack/lib/action_dispatch/middleware/callbacks.rb
  22. +216 −0 actionpack/lib/action_dispatch/middleware/cookies.rb
  23. +24 −0 actionpack/lib/action_dispatch/middleware/notifications.rb
  24. +22 −10 actionpack/lib/action_dispatch/middleware/show_exceptions.rb
  25. +8 −1 actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
  26. +3 −3 actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
  27. +1 −1  actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
  28. +29 −0 actionpack/lib/action_dispatch/railtie.rb
  29. +17 −0 actionpack/lib/action_dispatch/railties/subscriber.rb
  30. +4 −3 actionpack/lib/action_dispatch/routing.rb
  31. +26 −35 actionpack/lib/action_dispatch/routing/mapper.rb
  32. +8 −8 actionpack/lib/action_dispatch/testing/assertions/routing.rb
  33. +2 −2 actionpack/lib/action_view/helpers/debug_helper.rb
  34. +3 −0  actionpack/lib/action_view/helpers/form_tag_helper.rb
  35. +1 −1  actionpack/lib/action_view/helpers/sanitize_helper.rb
  36. +2 −4 actionpack/lib/action_view/helpers/text_helper.rb
  37. +1 −0  actionpack/test/abstract_unit.rb
  38. +2 −2 actionpack/test/activerecord/controller_runtime_test.rb
  39. +10 −27 actionpack/test/controller/cookie_test.rb
  40. +0 −27 actionpack/test/controller/filter_params_test.rb
  41. +1 −1  actionpack/test/controller/flash_test.rb
  42. +27 −1 actionpack/test/controller/new_base/base_test.rb
  43. +14 −28 actionpack/test/controller/subscriber_test.rb
  44. +0 −12 actionpack/test/dispatch/callbacks_test.rb
  45. +3 −6 actionpack/test/dispatch/response_test.rb
  46. +10 −10 actionpack/test/dispatch/routing_test.rb
  47. +2 −2 actionpack/test/dispatch/session/cookie_store_test.rb
  48. +12 −33 actionpack/test/dispatch/show_exceptions_test.rb
  49. +112 −0 actionpack/test/dispatch/subscriber_test.rb
  50. +1 −1  actionpack/test/fixtures/reply.rb
  51. +52 −16 activemodel/README
  52. +73 −31 activemodel/lib/active_model/callbacks.rb
  53. +12 −1 activemodel/lib/active_model/conversion.rb
  54. +39 −1 activemodel/lib/active_model/dirty.rb
  55. +2 −0  activemodel/lib/active_model/errors.rb
  56. +4 −4 activemodel/lib/active_model/validations/length.rb
  57. +2 −0  activemodel/lib/active_model/validations/validates.rb
  58. +8 −0 activemodel/test/cases/validations_test.rb
  59. +10 −0 activerecord/CHANGELOG
  60. +16 −17 activerecord/lib/active_record/association_preload.rb
  61. +10 −32 activerecord/lib/active_record/associations.rb
  62. +0 −2  activerecord/lib/active_record/associations/association_collection.rb
  63. +1 −1  activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
  64. +1 −1  activerecord/lib/active_record/associations/has_many_association.rb
  65. +1 −1  activerecord/lib/active_record/associations/has_many_through_association.rb
  66. +5 −5 activerecord/lib/active_record/autosave_association.rb
  67. +21 −55 activerecord/lib/active_record/base.rb
  68. +9 −81 activerecord/lib/active_record/calculations.rb
  69. +1 −1  activerecord/lib/active_record/callbacks.rb
  70. +6 −7 activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
  71. +1 −2  activerecord/lib/active_record/fixtures.rb
  72. +1 −1  activerecord/lib/active_record/locking/optimistic.rb
  73. +2 −1  activerecord/lib/active_record/migration.rb
  74. +69 −84 activerecord/lib/active_record/named_scope.rb
  75. +5 −5 activerecord/lib/active_record/nested_attributes.rb
  76. +1 −1  activerecord/lib/active_record/railties/databases.rake
  77. +1 −1  activerecord/lib/active_record/railties/subscriber.rb
  78. +15 −32 activerecord/lib/active_record/relation.rb
  79. +2 −2 activerecord/lib/active_record/relation/calculation_methods.rb
  80. +42 −0 activerecord/lib/active_record/relation/finder_methods.rb
  81. +2 −1  activerecord/lib/active_record/relation/predicate_builder.rb
  82. +33 −6 activerecord/lib/active_record/relation/spawn_methods.rb
  83. +2 −2 activerecord/lib/active_record/transactions.rb
  84. +11 −1 activerecord/lib/active_record/validations.rb
  85. +1 −1  activerecord/lib/active_record/validations/uniqueness.rb
  86. +8 −0 {railties/lib/rails → activerecord/lib}/generators/active_record.rb
  87. +1 −1  {railties/lib/rails → activerecord/lib}/generators/active_record/migration/migration_generator.rb
  88. 0  {railties/lib/rails → activerecord/lib}/generators/active_record/migration/templates/migration.rb
  89. +1 −1  {railties/lib/rails → activerecord/lib}/generators/active_record/model/model_generator.rb
  90. 0  {railties/lib/rails → activerecord/lib}/generators/active_record/model/templates/migration.rb
  91. 0  {railties/lib/rails → activerecord/lib}/generators/active_record/model/templates/model.rb
  92. +1 −1  {railties/lib/rails → activerecord/lib}/generators/active_record/observer/observer_generator.rb
  93. 0  {railties/lib/rails → activerecord/lib}/generators/active_record/observer/templates/observer.rb
  94. +1 −1  ...ib/rails → activerecord/lib}/generators/active_record/session_migration/session_migration_generator.rb
  95. 0  {railties/lib/rails → activerecord/lib}/generators/active_record/session_migration/templates/migration.rb
  96. +6 −6 activerecord/test/cases/autosave_association_test.rb
  97. +3 −1 activerecord/test/cases/base_test.rb
  98. +0 −17 activerecord/test/cases/calculations_test.rb
  99. +7 −7 activerecord/test/cases/method_scoping_test.rb
  100. +24 −19 activerecord/test/cases/named_scope_test.rb
  101. +10 −7 activerecord/test/cases/relations_test.rb
  102. +0 −43 activerecord/test/cases/schema_definitions_test.rb
  103. +27 −2 activerecord/test/cases/validations_test.rb
  104. +3 −3 activerecord/test/models/comment.rb
  105. +3 −5 activerecord/test/models/company.rb
  106. +2 −2 activerecord/test/models/developer.rb
  107. +1 −1  activerecord/test/models/organization.rb
  108. +2 −2 activerecord/test/models/person.rb
  109. +9 −9 activerecord/test/models/post.rb
  110. +1 −1  activerecord/test/models/reply.rb
  111. +11 −11 activerecord/test/models/topic.rb
  112. +7 −0 activeresource/lib/active_resource/base.rb
  113. +12 −3 activeresource/lib/active_resource/validations.rb
  114. +13 −0 activeresource/test/cases/validations_test.rb
  115. +24 −8 activesupport/lib/active_support/backtrace_cleaner.rb
  116. +4 −4 activesupport/lib/active_support/cache.rb
  117. +1 −1  activesupport/lib/active_support/callbacks.rb
  118. +1 −1  activesupport/lib/active_support/core_ext/array/access.rb
  119. +9 −0 activesupport/lib/active_support/core_ext/array/wrap.rb
  120. +0 −47 activesupport/lib/active_support/core_ext/exception.rb
  121. +48 −0 activesupport/lib/active_support/core_ext/hash/conversions.rb
  122. +8 −0 activesupport/lib/active_support/core_ext/hash/except.rb
  123. +5 −0 activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
  124. +4 −2 activesupport/lib/active_support/core_ext/hash/keys.rb
  125. +16 −0 activesupport/lib/active_support/core_ext/object/duplicable.rb
  126. +4 −1 activesupport/lib/active_support/core_ext/rexml.rb
  127. +2 −2 activesupport/lib/active_support/core_ext/string/access.rb
  128. +1 −1  activesupport/lib/active_support/multibyte/chars.rb
  129. +1 −1  activesupport/lib/active_support/notifications.rb
  130. +9 −0 activesupport/lib/active_support/notifications/instrumenter.rb
  131. +0 −69 activesupport/test/core_ext/exception_test.rb
  132. +16 −0 activesupport/test/notifications_test.rb
  133. +53 −9 railties/README
  134. +1 −1  railties/bin/rails
  135. +8 −7 railties/guides/rails_guides.rb
  136. +14 −8 railties/guides/rails_guides/generator.rb
  137. +2 −2 railties/guides/rails_guides/indexer.rb
  138. +9 −9 railties/guides/source/2_2_release_notes.textile
  139. +3 −3 railties/guides/source/2_3_release_notes.textile
  140. +1 −3 railties/guides/source/action_mailer_basics.textile
  141. +1,423 −11 railties/guides/source/action_view_overview.textile
  142. +102 −33 railties/guides/source/active_record_basics.textile
  143. +1,835 −0 railties/guides/source/active_support_core_extensions.textile
  144. +0 −818 railties/guides/source/active_support_overview.textile
  145. +41 −0 railties/guides/source/activerecord_validations_callbacks.textile
  146. +285 −37 railties/guides/source/ajax_on_rails.textile
  147. +1 −1  railties/guides/source/association_basics.textile
  148. +4 −0 railties/guides/source/caching_with_rails.textile
  149. +115 −59 railties/guides/source/configuring.textile
  150. +31 −7 railties/guides/source/contributing_to_rails.textile
  151. 0  railties/guides/source/{credits.erb.textile → credits.textile.erb}
  152. +1 −1  railties/guides/source/debugging_rails_applications.textile
  153. +2 −2 railties/guides/source/form_helpers.textile
  154. +378 −0 railties/guides/source/generators.textile
  155. +5 −5 railties/guides/source/getting_started.textile
  156. +1 −1  railties/guides/source/i18n.textile
  157. 0  railties/guides/source/{index.erb.textile → index.textile.erb}
  158. +1 −1  railties/guides/source/layout.html.erb
  159. +1 −1  railties/guides/source/migrations.textile
  160. +1 −1  railties/guides/source/plugins.textile
  161. +1 −1  railties/guides/source/rails_on_rack.textile
  162. +3 −3 railties/guides/source/routing.textile
  163. +26 −28 railties/guides/source/security.textile
  164. +37 −44 railties/guides/source/testing.textile
  165. 0  railties/lib/{rails → }/generators/erb.rb
  166. +1 −1  railties/lib/{rails → }/generators/erb/controller/controller_generator.rb
  167. 0  railties/lib/{rails → }/generators/erb/controller/templates/view.html.erb
  168. +1 −1  railties/lib/{rails → }/generators/erb/mailer/mailer_generator.rb
  169. 0  railties/lib/{rails → }/generators/erb/mailer/templates/view.erb
  170. +1 −1  railties/lib/{rails → }/generators/erb/scaffold/scaffold_generator.rb
  171. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/_form.html.erb
  172. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/edit.html.erb
  173. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/index.html.erb
  174. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/layout.html.erb
  175. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/new.html.erb
  176. 0  railties/lib/{rails → }/generators/erb/scaffold/templates/show.html.erb
  177. 0  railties/lib/{rails → }/generators/rails/app/USAGE
  178. +3 −3 railties/lib/{rails → }/generators/rails/app/app_generator.rb
  179. 0  railties/lib/{rails → }/generators/rails/app/templates/Gemfile
  180. 0  railties/lib/{rails → }/generators/rails/app/templates/README
  181. 0  railties/lib/{rails → }/generators/rails/app/templates/Rakefile
  182. 0  railties/lib/{rails → }/generators/rails/app/templates/app/controllers/application_controller.rb
  183. 0  railties/lib/{rails → }/generators/rails/app/templates/app/helpers/application_helper.rb
  184. 0  ...tors/rails/generator/templates/templates → generators/rails/app/templates/app/models}/.empty_directory
  185. 0  ...ors/rails/app/templates/test/unit → generators/rails/app/templates/app/views/layouts}/.empty_directory
  186. 0  railties/lib/{rails → }/generators/rails/app/templates/config.ru
  187. 0  railties/lib/{rails → }/generators/rails/app/templates/config/application.rb
  188. +12 −1 railties/lib/{rails → }/generators/rails/app/templates/config/boot.rb
  189. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/frontbase.yml
  190. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/ibm_db.yml
  191. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/mysql.yml
  192. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/oracle.yml
  193. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/postgresql.yml
  194. 0  railties/lib/{rails → }/generators/rails/app/templates/config/databases/sqlite3.yml
  195. 0  railties/lib/{rails → }/generators/rails/app/templates/config/environment.rb
  196. 0  railties/lib/{rails → }/generators/rails/app/templates/config/environments/development.rb.tt
  197. 0  railties/lib/{rails → }/generators/rails/app/templates/config/environments/production.rb.tt
  198. 0  railties/lib/{rails → }/generators/rails/app/templates/config/environments/test.rb.tt
  199. 0  railties/lib/{rails → }/generators/rails/app/templates/config/initializers/backtrace_silencers.rb
  200. 0  ...ies/lib/{rails → }/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt
  201. 0  railties/lib/{rails → }/generators/rails/app/templates/config/initializers/inflections.rb
  202. 0  railties/lib/{rails → }/generators/rails/app/templates/config/initializers/mime_types.rb
  203. 0  railties/lib/{rails → }/generators/rails/app/templates/config/initializers/session_store.rb.tt
  204. 0  railties/lib/{rails → }/generators/rails/app/templates/config/locales/en.yml
  205. 0  railties/lib/{rails → }/generators/rails/app/templates/config/routes.rb
  206. 0  railties/lib/{rails → }/generators/rails/app/templates/db/seeds.rb
  207. 0  railties/lib/{rails → }/generators/rails/app/templates/doc/README_FOR_APP
  208. 0  railties/lib/{rails → }/generators/rails/app/templates/gitignore
  209. 0  railties/lib/{rails → }/generators/rails/app/templates/public/404.html
  210. 0  railties/lib/{rails → }/generators/rails/app/templates/public/422.html
  211. 0  railties/lib/{rails → }/generators/rails/app/templates/public/500.html
  212. 0  railties/lib/{rails → }/generators/rails/app/templates/public/favicon.ico
  213. 0  railties/lib/{rails → }/generators/rails/app/templates/public/images/rails.png
  214. 0  railties/lib/{rails → }/generators/rails/app/templates/public/index.html
  215. 0  railties/lib/{rails → }/generators/rails/app/templates/public/javascripts/application.js
  216. 0  railties/lib/{rails → }/generators/rails/app/templates/public/javascripts/controls.js
  217. 0  railties/lib/{rails → }/generators/rails/app/templates/public/javascripts/dragdrop.js
  218. 0  railties/lib/{rails → }/generators/rails/app/templates/public/javascripts/effects.js
  219. 0  railties/lib/{rails → }/generators/rails/app/templates/public/javascripts/prototype.js
  220. 0  railties/lib/{rails → }/generators/rails/app/templates/public/robots.txt
  221. 0  ...s/app/templates/test/integration → generators/rails/app/templates/public/stylesheets}/.empty_directory
  222. 0  railties/lib/{rails → }/generators/rails/app/templates/script/about
  223. 0  railties/lib/{rails → }/generators/rails/app/templates/script/console.tt
  224. 0  railties/lib/{rails → }/generators/rails/app/templates/script/dbconsole.tt
  225. 0  railties/lib/{rails → }/generators/rails/app/templates/script/destroy
  226. 0  railties/lib/{rails → }/generators/rails/app/templates/script/generate
  227. 0  railties/lib/{rails → }/generators/rails/app/templates/script/performance/benchmarker
  228. 0  railties/lib/{rails → }/generators/rails/app/templates/script/performance/profiler
  229. 0  railties/lib/{rails → }/generators/rails/app/templates/script/plugin
  230. 0  railties/lib/{rails → }/generators/rails/app/templates/script/runner
  231. 0  railties/lib/{rails → }/generators/rails/app/templates/script/server.tt
  232. 0  ...s/rails/app/templates/test/functional → generators/rails/app/templates/test/fixtures}/.empty_directory
  233. 0  ...s/rails/app/templates/test/fixtures → generators/rails/app/templates/test/functional}/.empty_directory
  234. 0  ...s/app/templates/public/stylesheets → generators/rails/app/templates/test/integration}/.empty_directory
  235. 0  railties/lib/{rails → }/generators/rails/app/templates/test/performance/browsing_test.rb
  236. 0  railties/lib/{rails → }/generators/rails/app/templates/test/test_helper.rb
  237. 0  ...ors/rails/app/templates/app/views/layouts → generators/rails/app/templates/test/unit}/.empty_directory
  238. 0  railties/lib/{rails → }/generators/rails/controller/USAGE
  239. 0  railties/lib/{rails → }/generators/rails/controller/controller_generator.rb
  240. 0  railties/lib/{rails → }/generators/rails/controller/templates/controller.rb
  241. 0  railties/lib/{rails → }/generators/rails/generator/USAGE
  242. 0  railties/lib/{rails → }/generators/rails/generator/generator_generator.rb
  243. 0  railties/lib/{rails → }/generators/rails/generator/templates/%file_name%_generator.rb.tt
  244. 0  railties/lib/{rails → }/generators/rails/generator/templates/USAGE.tt
  245. 0  ...tors/rails/app/templates/app/models → generators/rails/generator/templates/templates}/.empty_directory
  246. 0  railties/lib/{rails → }/generators/rails/helper/USAGE
  247. 0  railties/lib/{rails → }/generators/rails/helper/helper_generator.rb
  248. 0  railties/lib/{rails → }/generators/rails/helper/templates/helper.rb
  249. 0  railties/lib/{rails → }/generators/rails/integration_test/USAGE
  250. 0  railties/lib/{rails → }/generators/rails/integration_test/integration_test_generator.rb
  251. +2 −2 railties/lib/{rails → }/generators/rails/mailer/USAGE
  252. +1 −1  railties/lib/{rails → }/generators/rails/mailer/mailer_generator.rb
  253. 0  railties/lib/{rails → }/generators/rails/mailer/templates/mailer.rb
  254. 0  railties/lib/{rails → }/generators/rails/metal/USAGE
  255. 0  railties/lib/{rails → }/generators/rails/metal/metal_generator.rb
  256. 0  railties/lib/{rails → }/generators/rails/metal/templates/metal.rb
  257. 0  railties/lib/{rails → }/generators/rails/migration/USAGE
  258. 0  railties/lib/{rails → }/generators/rails/migration/migration_generator.rb
  259. 0  railties/lib/{rails → }/generators/rails/model/USAGE
  260. 0  railties/lib/{rails → }/generators/rails/model/model_generator.rb
  261. +1 −0  railties/lib/{rails → }/generators/rails/model_subclass/model_subclass_generator.rb
  262. 0  railties/lib/{rails → }/generators/rails/observer/USAGE
  263. 0  railties/lib/{rails → }/generators/rails/observer/observer_generator.rb
  264. 0  railties/lib/{rails → }/generators/rails/performance_test/USAGE
  265. 0  railties/lib/{rails → }/generators/rails/performance_test/performance_test_generator.rb
  266. 0  railties/lib/{rails → }/generators/rails/plugin/USAGE
  267. +7 −7 railties/lib/{rails → }/generators/rails/plugin/plugin_generator.rb
  268. 0  ...ails/generators/rails/plugin/templates/MIT-LICENSE → generators/rails/plugin/templates/MIT-LICENSE.tt}
  269. 0  ...ies/lib/{rails/generators/rails/plugin/templates/README → generators/rails/plugin/templates/README.tt}
  270. 0  ...lib/{rails/generators/rails/plugin/templates/Rakefile → generators/rails/plugin/templates/Rakefile.tt}
  271. 0  railties/lib/{rails → }/generators/rails/plugin/templates/init.rb
  272. 0  railties/lib/{rails → }/generators/rails/plugin/templates/install.rb
  273. 0  railties/lib/{rails → }/generators/rails/plugin/templates/lib/%file_name%.rb.tt
  274. 0  railties/lib/{rails → }/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt
  275. 0  railties/lib/{rails → }/generators/rails/plugin/templates/uninstall.rb
  276. 0  railties/lib/{rails → }/generators/rails/resource/USAGE
  277. +1 −1  railties/lib/{rails → }/generators/rails/resource/resource_generator.rb
  278. 0  railties/lib/{rails → }/generators/rails/scaffold/USAGE
  279. +1 −1  railties/lib/{rails → }/generators/rails/scaffold/scaffold_generator.rb
  280. 0  railties/lib/{rails → }/generators/rails/scaffold_controller/USAGE
  281. 0  railties/lib/{rails → }/generators/rails/scaffold_controller/scaffold_controller_generator.rb
  282. 0  railties/lib/{rails → }/generators/rails/scaffold_controller/templates/controller.rb
  283. 0  railties/lib/{rails → }/generators/rails/session_migration/USAGE
  284. 0  railties/lib/{rails → }/generators/rails/session_migration/session_migration_generator.rb
  285. 0  railties/lib/{rails → }/generators/rails/stylesheets/USAGE
  286. 0  railties/lib/{rails → }/generators/rails/stylesheets/stylesheets_generator.rb
  287. 0  railties/lib/{rails → }/generators/rails/stylesheets/templates/scaffold.css
  288. 0  railties/lib/{rails → }/generators/test_unit.rb
  289. +1 −1  railties/lib/{rails → }/generators/test_unit/controller/controller_generator.rb
  290. 0  railties/lib/{rails → }/generators/test_unit/controller/templates/functional_test.rb
  291. +1 −1  railties/lib/{rails → }/generators/test_unit/helper/helper_generator.rb
  292. 0  railties/lib/{rails → }/generators/test_unit/helper/templates/helper_test.rb
  293. +1 −1  railties/lib/{rails → }/generators/test_unit/integration/integration_generator.rb
  294. 0  railties/lib/{rails → }/generators/test_unit/integration/templates/integration_test.rb
  295. +2 −2 railties/lib/{rails → }/generators/test_unit/mailer/mailer_generator.rb
  296. 0  railties/lib/{rails → }/generators/test_unit/mailer/templates/fixture
  297. 0  ...rs/test_unit/mailer/templates/unit_test.rb → generators/test_unit/mailer/templates/functional_test.rb}
  298. +1 −1  railties/lib/{rails → }/generators/test_unit/model/model_generator.rb
  299. 0  railties/lib/{rails → }/generators/test_unit/model/templates/fixtures.yml
  300. 0  railties/lib/{rails → }/generators/test_unit/model/templates/unit_test.rb
Sorry, we could not display the entire diff because too many files (368) changed.
View
43 actionmailer/lib/action_mailer/base.rb
@@ -23,8 +23,7 @@ module ActionMailer #:nodoc:
# bcc ["bcc@example.com", "Order Watcher <watcher@example.com>"]
# from "system@example.com"
# subject "New account information"
- #
- # @account = recipient
+ # body :account => recipient
# end
# end
#
@@ -36,7 +35,7 @@ module ActionMailer #:nodoc:
# * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header.
# * <tt>bcc</tt> - Takes one or more email addresses. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc:</tt> header.
# * <tt>reply_to</tt> - Takes one or more email addresses. These addresses will be listed as the default recipients when replying to your email. Sets the <tt>Reply-To:</tt> header.
- # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent.
+ # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header will be set by the delivery agent.
# * <tt>content_type</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>.
# * <tt>headers</tt> - Specify additional headers to be set for the message, e.g. <tt>headers 'X-Mail-Count' => 107370</tt>.
#
@@ -144,12 +143,13 @@ module ActionMailer #:nodoc:
# subject "New account information"
# from "system@example.com"
# content_type "multipart/alternative"
+ # body :account => recipient
#
# part :content_type => "text/html",
- # :body => render_message("signup-as-html", :account => recipient)
+ # :data => render_message("signup-as-html")
#
# part "text/plain" do |p|
- # p.body = render_message("signup-as-plain", :account => recipient)
+ # p.body = render_message("signup-as-plain")
# p.content_transfer_encoding = "base64"
# end
# end
@@ -492,11 +492,13 @@ def matches_dynamic_method?(method_name) #:nodoc:
# body, headers, etc.) can be set on it.
def part(params)
params = {:content_type => params} if String === params
+
if custom_headers = params.delete(:headers)
ActiveSupport::Deprecation.warn('Passing custom headers with :headers => {} is deprecated. ' <<
'Please just pass in custom headers directly.', caller[0,10])
params.merge!(custom_headers)
end
+
part = Mail::Part.new(params)
yield part if block_given?
@parts << part
@@ -514,6 +516,20 @@ def attachment(params, &block)
part(params, &block)
end
+ # Allow you to set assigns for your template:
+ #
+ # body :greetings => "Hi"
+ #
+ # Will make @greetings available in the template to be rendered.
+ def body(object=nil)
+ returning(super) do # Run deprecation hooks
+ if object.is_a?(Hash)
+ @assigns_set = true
+ object.each { |k, v| instance_variable_set(:"@#{k}", v) }
+ end
+ end
+ end
+
# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
# will be initialized according to the named method. If not, the mailer will
# remain uninitialized (useful when you only need to invoke the "receive"
@@ -549,6 +565,23 @@ def deliver!(mail = @mail)
private
+ # Render a message but does not set it as mail body. Useful for rendering
+ # data for part and attachments.
+ #
+ # Examples:
+ #
+ # render_message "special_message"
+ # render_message :template => "special_message"
+ # render_message :inline => "<%= 'Hi!' %>"
+ def render_message(object)
+ case object
+ when String
+ render_to_body(:template => object)
+ else
+ render_to_body(object)
+ end
+ end
+
# Set up the default values for the various instance variables of this
# mailer. Subclasses may override this method to provide different
# defaults.
View
38 actionmailer/lib/action_mailer/deprecated_body.rb
@@ -1,15 +1,13 @@
module ActionMailer
# TODO Remove this module all together in a next release. Ensure that super
- # hooks in ActionMailer::Base are removed as well.
+ # hooks and @assigns_set in ActionMailer::Base are removed as well.
module DeprecatedBody
- def self.included(base)
- base.class_eval do
- # Define the body of the message. This is either a Hash (in which case it
- # specifies the variables to pass to the template when it is rendered),
- # or a string, in which case it specifies the actual text of the message.
- adv_attr_accessor :body
- end
- end
+ extend ActionMailer::AdvAttrAccessor
+
+ # Define the body of the message. This is either a Hash (in which case it
+ # specifies the variables to pass to the template when it is rendered),
+ # or a string, in which case it specifies the actual text of the message.
+ adv_attr_accessor :body
def initialize_defaults(method_name)
@body ||= {}
@@ -18,32 +16,28 @@ def initialize_defaults(method_name)
def attachment(params, &block)
if params[:body]
ActiveSupport::Deprecation.warn('attachment :body => "string" is deprecated. To set the body of an attachment ' <<
- 'please use :data instead, like attachment :data => "string".', caller[0,10])
+ 'please use :data instead, like attachment :data => "string"', caller[0,10])
params[:data] = params.delete(:body)
end
end
def create_parts
- if String === @body
- ActiveSupport::Deprecation.warn('body is deprecated. To set the body with a text ' <<
- 'call render(:text => "body").', caller[0,10])
+ if String === @body && !defined?(@assigns_set)
+ ActiveSupport::Deprecation.warn('body(String) is deprecated. To set the body with a text ' <<
+ 'call render(:text => "body")', caller[0,10])
self.response_body = @body
- elsif @body.is_a?(Hash) && !@body.empty?
- ActiveSupport::Deprecation.warn('body is deprecated. To set assigns simply ' <<
- 'use instance variables', caller[0,10])
- @body.each { |k, v| instance_variable_set(:"@#{k}", v) }
+ elsif self.response_body
+ @body = self.response_body
end
end
def render(*args)
options = args.last.is_a?(Hash) ? args.last : {}
if options[:body]
- ActiveSupport::Deprecation.warn(':body is deprecated. To set assigns simply ' <<
- 'use instance variables', caller[0,1])
+ ActiveSupport::Deprecation.warn(':body in render deprecated. Please call body ' <<
+ 'with a hash instead', caller[0,1])
- options.delete(:body).each do |k, v|
- instance_variable_set(:"@#{k}", v)
- end
+ body options.delete(:body)
end
super
View
10 actionmailer/test/mail_service_test.rb
@@ -120,11 +120,11 @@ def multipart_with_mime_version(recipient)
content_type "multipart/alternative"
part "text/plain" do |p|
- p.body = "blah"
+ p.body = render_message(:text => "blah")
end
part "text/html" do |p|
- p.body = "<b>blah</b>"
+ p.body = render_message(:inline => "<%= content_tag(:b, 'blah') %>")
end
end
@@ -301,7 +301,6 @@ def return_path
render :text => "testing"
end
- # This tests body calls accepeting a hash, which is deprecated.
def body_ivar(recipient)
recipients recipient
subject "Body as a local variable"
@@ -1075,7 +1074,7 @@ def test_return_path_with_create
def test_return_path_with_create
mail = TestMailer.create_return_path
- assert_equal "another@somewhere.test", mail.return_path
+ assert_equal ["another@somewhere.test"], mail.return_path
end
def test_return_path_with_deliver
@@ -1086,8 +1085,7 @@ def test_return_path_with_deliver
end
def test_body_is_stored_as_an_ivar
- mail = nil
- ActiveSupport::Deprecation.silence { mail = TestMailer.create_body_ivar(@recipient) }
+ mail = TestMailer.create_body_ivar(@recipient)
assert_equal "body: foo\nbar: baz", mail.body.to_s
end
View
140 actionpack/lib/abstract_controller/base.rb
@@ -62,15 +62,19 @@ def hidden_actions
# Array[String]:: A list of all methods that should be considered
# actions.
def action_methods
- @action_methods ||=
+ @action_methods ||= begin
# All public instance methods of this class, including ancestors
- public_instance_methods(true).map { |m| m.to_s }.to_set -
- # Except for public instance methods of Base and its ancestors
- internal_methods.map { |m| m.to_s } +
- # Be sure to include shadowed public instance methods of this class
- public_instance_methods(false).map { |m| m.to_s } -
- # And always exclude explicitly hidden actions
- hidden_actions
+ methods = public_instance_methods(true).map { |m| m.to_s }.to_set -
+ # Except for public instance methods of Base and its ancestors
+ internal_methods.map { |m| m.to_s } +
+ # Be sure to include shadowed public instance methods of this class
+ public_instance_methods(false).map { |m| m.to_s } -
+ # And always exclude explicitly hidden actions
+ hidden_actions
+
+ # Clear out AS callback method pollution
+ methods.reject { |method| method =~ /_one_time_conditions/ }
+ end
end
# Returns the full controller name, underscored, without the ending Controller.
@@ -116,68 +120,72 @@ def controller_path
self.class.controller_path
end
- private
- # Returns true if the name can be considered an action. This can
- # be overridden in subclasses to modify the semantics of what
- # can be considered an action.
- #
- # ==== Parameters
- # name<String>:: The name of an action to be tested
- #
- # ==== Returns
- # TrueClass, FalseClass
- def action_method?(name)
- self.class.action_methods.include?(name)
+ def action_methods
+ self.class.action_methods
end
- # Call the action. Override this in a subclass to modify the
- # behavior around processing an action. This, and not #process,
- # is the intended way to override action dispatching.
- def process_action(method_name, *args)
- send_action(method_name, *args)
- end
+ private
+ # Returns true if the name can be considered an action. This can
+ # be overridden in subclasses to modify the semantics of what
+ # can be considered an action.
+ #
+ # ==== Parameters
+ # name<String>:: The name of an action to be tested
+ #
+ # ==== Returns
+ # TrueClass, FalseClass
+ def action_method?(name)
+ self.class.action_methods.include?(name)
+ end
- # Actually call the method associated with the action. Override
- # this method if you wish to change how action methods are called,
- # not to add additional behavior around it. For example, you would
- # override #send_action if you want to inject arguments into the
- # method.
- alias send_action send
-
- # If the action name was not found, but a method called "action_missing"
- # was found, #method_for_action will return "_handle_action_missing".
- # This method calls #action_missing with the current action name.
- def _handle_action_missing
- action_missing(@_action_name)
- end
+ # Call the action. Override this in a subclass to modify the
+ # behavior around processing an action. This, and not #process,
+ # is the intended way to override action dispatching.
+ def process_action(method_name, *args)
+ send_action(method_name, *args)
+ end
- # Takes an action name and returns the name of the method that will
- # handle the action. In normal cases, this method returns the same
- # name as it receives. By default, if #method_for_action receives
- # a name that is not an action, it will look for an #action_missing
- # method and return "_handle_action_missing" if one is found.
- #
- # Subclasses may override this method to add additional conditions
- # that should be considered an action. For instance, an HTTP controller
- # with a template matching the action name is considered to exist.
- #
- # If you override this method to handle additional cases, you may
- # also provide a method (like _handle_method_missing) to handle
- # the case.
- #
- # If none of these conditions are true, and method_for_action
- # returns nil, an ActionNotFound exception will be raised.
- #
- # ==== Parameters
- # action_name<String>:: An action name to find a method name for
- #
- # ==== Returns
- # String:: The name of the method that handles the action
- # nil:: No method name could be found. Raise ActionNotFound.
- def method_for_action(action_name)
- if action_method?(action_name) then action_name
- elsif respond_to?(:action_missing, true) then "_handle_action_missing"
+ # Actually call the method associated with the action. Override
+ # this method if you wish to change how action methods are called,
+ # not to add additional behavior around it. For example, you would
+ # override #send_action if you want to inject arguments into the
+ # method.
+ alias send_action send
+
+ # If the action name was not found, but a method called "action_missing"
+ # was found, #method_for_action will return "_handle_action_missing".
+ # This method calls #action_missing with the current action name.
+ def _handle_action_missing
+ action_missing(@_action_name)
+ end
+
+ # Takes an action name and returns the name of the method that will
+ # handle the action. In normal cases, this method returns the same
+ # name as it receives. By default, if #method_for_action receives
+ # a name that is not an action, it will look for an #action_missing
+ # method and return "_handle_action_missing" if one is found.
+ #
+ # Subclasses may override this method to add additional conditions
+ # that should be considered an action. For instance, an HTTP controller
+ # with a template matching the action name is considered to exist.
+ #
+ # If you override this method to handle additional cases, you may
+ # also provide a method (like _handle_method_missing) to handle
+ # the case.
+ #
+ # If none of these conditions are true, and method_for_action
+ # returns nil, an ActionNotFound exception will be raised.
+ #
+ # ==== Parameters
+ # action_name<String>:: An action name to find a method name for
+ #
+ # ==== Returns
+ # String:: The name of the method that handles the action
+ # nil:: No method name could be found. Raise ActionNotFound.
+ def method_for_action(action_name)
+ if action_method?(action_name) then action_name
+ elsif respond_to?(:action_missing, true) then "_handle_action_missing"
+ end
end
- end
end
end
View
2  actionpack/lib/abstract_controller/rendering.rb
@@ -42,7 +42,7 @@ def view_context
# Delegates render_to_body and sticks the result in self.response_body.
def render(*args)
if response_body
- raise AbstractController::DoubleRenderError, "OMG"
+ raise AbstractController::DoubleRenderError, "Can only render or redirect once per action"
end
self.response_body = render_to_body(*args)
View
5 actionpack/lib/action_controller/deprecated/dispatcher.rb
@@ -1,8 +1,5 @@
module ActionController
class Dispatcher
- cattr_accessor :prepare_each_request
- self.prepare_each_request = false
-
class << self
def before_dispatch(*args, &block)
ActiveSupport::Deprecation.warn "ActionController::Dispatcher.before_dispatch is deprecated. " <<
@@ -18,7 +15,7 @@ def after_dispatch(*args, &block)
def to_prepare(*args, &block)
ActiveSupport::Deprecation.warn "ActionController::Dispatcher.to_prepare is deprecated. " <<
- "Please use ActionDispatch::Callbacks.to_prepare instead.", caller
+ "Please use config.to_prepare instead", caller
ActionDispatch::Callbacks.after(*args, &block)
end
View
186 actionpack/lib/action_controller/metal/cookies.rb
@@ -1,48 +1,4 @@
module ActionController #:nodoc:
- # Cookies are read and written through ActionController#cookies.
- #
- # The cookies being read are the ones received along with the request, the cookies
- # being written will be sent out with the response. Reading a cookie does not get
- # the cookie object itself back, just the value it holds.
- #
- # Examples for writing:
- #
- # # Sets a simple session cookie.
- # cookies[:user_name] = "david"
- #
- # # Sets a cookie that expires in 1 hour.
- # cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now }
- #
- # Examples for reading:
- #
- # cookies[:user_name] # => "david"
- # cookies.size # => 2
- #
- # Example for deleting:
- #
- # cookies.delete :user_name
- #
- # Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
- #
- # cookies[:key] = {
- # :value => 'a yummy cookie',
- # :expires => 1.year.from_now,
- # :domain => 'domain.com'
- # }
- #
- # cookies.delete(:key, :domain => 'domain.com')
- #
- # The option symbols for setting cookies are:
- #
- # * <tt>:value</tt> - The cookie's value or list of values (as an array).
- # * <tt>:path</tt> - The path for which this cookie applies. Defaults to the root
- # of the application.
- # * <tt>:domain</tt> - The domain for which this cookie applies.
- # * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
- # * <tt>:secure</tt> - Whether this cookie is a only transmitted to HTTPS servers.
- # Default is +false+.
- # * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
- # only HTTP. Defaults to +false+.
module Cookies
extend ActiveSupport::Concern
@@ -52,146 +8,10 @@ module Cookies
helper_method :cookies
cattr_accessor :cookie_verifier_secret
end
-
- protected
- # Returns the cookie container, which operates as described above.
+
+ private
def cookies
- @cookies ||= CookieJar.build(request, response)
- end
- end
-
- class CookieJar < Hash #:nodoc:
- def self.build(request, response)
- new.tap do |hash|
- hash.update(request.cookies)
- hash.response = response
- end
- end
-
- attr_accessor :response
-
- # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
- def [](name)
- super(name.to_s)
- end
-
- # Sets the cookie named +name+. The second argument may be the very cookie
- # value, or a hash of options as documented above.
- def []=(key, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
- value = options[:value]
- else
- value = options
- options = { :value => value }
+ request.cookie_jar
end
-
- super(key.to_s, value)
-
- options[:path] ||= "/"
- response.set_cookie(key, options)
- end
-
- # Removes the cookie on the client machine by setting the value to an empty string
- # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
- # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
- def delete(key, options = {})
- options.symbolize_keys!
- options[:path] ||= "/"
- value = super(key.to_s)
- response.delete_cookie(key, options)
- value
- end
-
- # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example:
- #
- # cookies.permanent[:prefers_open_id] = true
- # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
- #
- # This jar is only meant for writing. You'll read permanent cookies through the regular accessor.
- #
- # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples:
- #
- # cookies.permanent.signed[:remember_me] = current_user.id
- # # => Set-Cookie: discount=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
- def permanent
- @permanent ||= PermanentCookieJar.new(self)
- end
-
- # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from
- # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
- # cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will
- # be raised.
- #
- # This jar requires that you set a suitable secret for the verification on ActionController::Base.cookie_verifier_secret.
- #
- # Example:
- #
- # cookies.signed[:discount] = 45
- # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/
- #
- # cookies.signed[:discount] # => 45
- def signed
- @signed ||= SignedCookieJar.new(self)
- end
- end
-
- class PermanentCookieJar < CookieJar #:nodoc:
- def initialize(parent_jar)
- @parent_jar = parent_jar
- end
-
- def []=(key, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
- else
- options = { :value => options }
- end
-
- options[:expires] = 20.years.from_now
- @parent_jar[key] = options
- end
-
- def signed
- @signed ||= SignedCookieJar.new(self)
- end
-
- def controller
- @parent_jar.controller
- end
-
- def method_missing(method, *arguments, &block)
- @parent_jar.send(method, *arguments, &block)
- end
- end
-
- class SignedCookieJar < CookieJar #:nodoc:
- def initialize(parent_jar)
- unless ActionController::Base.cookie_verifier_secret
- raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies"
- end
-
- @parent_jar = parent_jar
- @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret)
- end
-
- def [](name)
- @verifier.verify(@parent_jar[name])
- end
-
- def []=(key, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
- options[:value] = @verifier.generate(options[:value])
- else
- options = { :value => @verifier.generate(options) }
- end
-
- @parent_jar[key] = options
- end
-
- def method_missing(method, *arguments, &block)
- @parent_jar.send(method, *arguments, &block)
- end
end
end
View
4 actionpack/lib/action_controller/metal/instrumentation.rb
@@ -20,11 +20,7 @@ def process_action(action, *args)
result = super
payload[:controller] = self.class.name
payload[:action] = self.action_name
- payload[:formats] = request.formats.map(&:to_s)
- payload[:remote_ip] = request.remote_ip
- payload[:method] = request.method
payload[:status] = response.status
- payload[:request_uri] = request.request_uri rescue "unknown"
append_info_to_payload(payload)
result
end
View
34 actionpack/lib/action_controller/metal/responder.rb
@@ -1,7 +1,7 @@
module ActionController #:nodoc:
- # Responder is responsible to expose a resource for different mime requests,
+ # Responder is responsible for exposing a resource to different mime requests,
# usually depending on the HTTP verb. The responder is triggered when
- # respond_with is called. The simplest case to study is a GET request:
+ # <code>respond_with</code> is called. The simplest case to study is a GET request:
#
# class PeopleController < ApplicationController
# respond_to :html, :xml, :json
@@ -12,17 +12,17 @@ module ActionController #:nodoc:
# end
# end
#
- # When a request comes, for example with format :xml, three steps happen:
+ # When a request comes in, for example for an XML response, three steps happen:
#
- # 1) responder searches for a template at people/index.xml;
+ # 1) the responder searches for a template at people/index.xml;
#
- # 2) if the template is not available, it will invoke :to_xml in the given resource;
+ # 2) if the template is not available, it will invoke <code>#to_xml</code> on the given resource;
#
- # 3) if the responder does not respond_to :to_xml, call :to_format on it.
+ # 3) if the responder does not <code>respond_to :to_xml</code>, call <code>#to_format</code> on it.
#
# === Builtin HTTP verb semantics
#
- # Rails default responder holds semantics for each HTTP verb. Depending on the
+ # The default Rails responder holds semantics for each HTTP verb. Depending on the
# content type, verb and the resource status, it will behave differently.
#
# Using Rails default responder, a POST request for creating an object could
@@ -55,7 +55,7 @@ module ActionController #:nodoc:
#
# === Nested resources
#
- # You can given nested resource as you do in form_for and polymorphic_url.
+ # You can supply nested resources as you do in <code>form_for</code> and <code>polymorphic_url</code>.
# Consider the project has many tasks example. The create action for
# TasksController would be like:
#
@@ -67,15 +67,15 @@ module ActionController #:nodoc:
# end
#
# Giving an array of resources, you ensure that the responder will redirect to
- # project_task_url instead of task_url.
+ # <code>project_task_url</code> instead of <code>task_url</code>.
#
- # Namespaced and singleton resources requires a symbol to be given, as in
+ # Namespaced and singleton resources require a symbol to be given, as in
# polymorphic urls. If a project has one manager which has many tasks, it
# should be invoked as:
#
# respond_with(@project, :manager, @task)
#
- # Check polymorphic_url documentation for more examples.
+ # Check <code>polymorphic_url</code> documentation for more examples.
#
class Responder
attr_reader :controller, :request, :format, :resource, :resources, :options
@@ -126,7 +126,7 @@ def to_html
navigation_behavior(e)
end
- # All others formats follow the procedure below. First we try to render a
+ # All other formats follow the procedure below. First we try to render a
# template, if the template is not available, we verify if the resource
# responds to :to_format and display it.
#
@@ -183,11 +183,11 @@ def default_render
@default_response.call
end
- # display is just a shortcut to render a resource with the current format.
+ # Display is just a shortcut to render a resource with the current format.
#
# display @user, :status => :ok
#
- # For xml request is equivalent to:
+ # For XML requests it's equivalent to:
#
# render :xml => @user, :status => :ok
#
@@ -204,14 +204,14 @@ def display(resource, given_options={})
controller.render given_options.merge!(options).merge!(format => resource)
end
- # Check if the resource has errors or not.
+ # Check whether the resource has errors.
#
def has_errors?
resource.respond_to?(:errors) && !resource.errors.empty?
end
- # By default, render the :edit action for html requests with failure, unless
- # the verb is post.
+ # By default, render the <code>:edit</code> action for HTML requests with failure, unless
+ # the verb is POST.
#
def default_action
@action ||= ACTIONS_FOR_VERBS[request.method]
View
3  actionpack/lib/action_controller/metal/testing.rb
@@ -10,6 +10,9 @@ def process_with_new_base_test(request, response)
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
+ if cookies = @_request.env['action_dispatch.cookies']
+ cookies.write(@_response)
+ end
@_response.body ||= self.response_body
@_response.prepare!
set_test_assigns
View
50 actionpack/lib/action_controller/railtie.rb
@@ -23,7 +23,6 @@ class Railtie < Rails::Railtie
initializer "action_controller.initialize_routing" do |app|
app.route_configuration_files << app.config.routes_configuration_file
app.route_configuration_files << app.config.builtin_routes_configuration_file
- app.reload_routes!
end
initializer "action_controller.initialize_framework_caches" do
@@ -40,54 +39,5 @@ class Railtie < Rails::Railtie
ActionController::Base.view_paths = view_path if ActionController::Base.view_paths.blank?
end
- class MetalMiddlewareBuilder
- def initialize(metals)
- @metals = metals
- end
-
- def new(app)
- ActionDispatch::Cascade.new(@metals, app)
- end
-
- def name
- ActionDispatch::Cascade.name
- end
- alias_method :to_s, :name
- end
-
- initializer "action_controller.initialize_metal" do |app|
- metal_root = "#{Rails.root}/app/metal"
- load_list = app.config.metals || Dir["#{metal_root}/**/*.rb"]
-
- metals = load_list.map { |metal|
- metal = File.basename(metal.gsub("#{metal_root}/", ''), '.rb')
- require_dependency metal
- metal.camelize.constantize
- }.compact
-
- middleware = MetalMiddlewareBuilder.new(metals)
- app.config.middleware.insert_before(:"ActionDispatch::ParamsParser", middleware)
- end
-
- # Prepare dispatcher callbacks and run 'prepare' callbacks
- initializer "action_controller.prepare_dispatcher" do |app|
- # TODO: This used to say unless defined?(Dispatcher). Find out why and fix.
- # Notice that at this point, ActionDispatch::Callbacks were already loaded.
- require 'rails/dispatcher'
- ActionController::Dispatcher.prepare_each_request = true unless app.config.cache_classes
-
- unless app.config.cache_classes
- # Setup dev mode route reloading
- routes_last_modified = app.routes_changed_at
- reload_routes = lambda do
- unless app.routes_changed_at == routes_last_modified
- routes_last_modified = app.routes_changed_at
- app.reload_routes!
- end
- end
- ActionDispatch::Callbacks.before { |callbacks| reload_routes.call }
- end
- end
-
end
end
View
7 actionpack/lib/action_controller/railties/subscriber.rb
@@ -3,18 +3,13 @@ module Railties
class Subscriber < Rails::Subscriber
def process_action(event)
payload = event.payload
-
- info "\nProcessed #{payload[:controller]}##{payload[:action]} " \
- "to #{payload[:formats].join(', ')} (for #{payload[:remote_ip]} at #{event.time.to_s(:db)}) " \
- "[#{payload[:method].to_s.upcase}]"
-
info " Parameters: #{payload[:params].inspect}" unless payload[:params].blank?
additions = ActionController::Base.log_process_action(payload)
message = "Completed in %.0fms" % event.duration
message << " (#{additions.join(" | ")})" unless additions.blank?
- message << " | #{payload[:status]} [#{payload[:request_uri]}]\n\n"
+ message << " by #{payload[:controller]}##{payload[:action]} [#{payload[:status]}]"
info(message)
end
View
12 actionpack/lib/action_dispatch.rb
@@ -43,8 +43,10 @@ module ActionDispatch
autoload_under 'middleware' do
autoload :Callbacks
autoload :Cascade
+ autoload :Cookies
autoload :Flash
autoload :Head
+ autoload :Notifications
autoload :ParamsParser
autoload :Rescue
autoload :ShowExceptions
@@ -55,7 +57,15 @@ module ActionDispatch
autoload :Routing
module Http
- autoload :Headers, 'action_dispatch/http/headers'
+ extend ActiveSupport::Autoload
+
+ autoload :Cache
+ autoload :Headers
+ autoload :MimeNegotiation
+ autoload :Parameters
+ autoload :Upload
+ autoload :UploadedFile, 'action_dispatch/http/upload'
+ autoload :URL
end
module Session
View
123 actionpack/lib/action_dispatch/http/cache.rb
@@ -0,0 +1,123 @@
+module ActionDispatch
+ module Http
+ module Cache
+ module Request
+ def if_modified_since
+ if since = env['HTTP_IF_MODIFIED_SINCE']
+ Time.rfc2822(since) rescue nil
+ end
+ end
+
+ def if_none_match
+ env['HTTP_IF_NONE_MATCH']
+ end
+
+ def not_modified?(modified_at)
+ if_modified_since && modified_at && if_modified_since >= modified_at
+ end
+
+ def etag_matches?(etag)
+ if_none_match && if_none_match == etag
+ end
+
+ # Check response freshness (Last-Modified and ETag) against request
+ # If-Modified-Since and If-None-Match conditions. If both headers are
+ # supplied, both must match, or the request is not considered fresh.
+ def fresh?(response)
+ last_modified = if_modified_since
+ etag = if_none_match
+
+ return false unless last_modified || etag
+
+ success = true
+ success &&= not_modified?(response.last_modified) if last_modified
+ success &&= etag_matches?(response.etag) if etag
+ success
+ end
+ end
+
+ module Response
+ def cache_control
+ @cache_control ||= {}
+ end
+
+ def last_modified
+ if last = headers['Last-Modified']
+ Time.httpdate(last)
+ end
+ end
+
+ def last_modified?
+ headers.include?('Last-Modified')
+ end
+
+ def last_modified=(utc_time)
+ headers['Last-Modified'] = utc_time.httpdate
+ end
+
+ def etag
+ @etag
+ end
+
+ def etag?
+ @etag
+ end
+
+ def etag=(etag)
+ key = ActiveSupport::Cache.expand_cache_key(etag)
+ @etag = %("#{Digest::MD5.hexdigest(key)}")
+ end
+
+ private
+
+ def handle_conditional_get!
+ if etag? || last_modified? || !@cache_control.empty?
+ set_conditional_cache_control!
+ elsif nonempty_ok_response?
+ self.etag = @body
+
+ if request && request.etag_matches?(etag)
+ self.status = 304
+ self.body = []
+ end
+
+ set_conditional_cache_control!
+ else
+ headers["Cache-Control"] = "no-cache"
+ end
+ end
+
+ def nonempty_ok_response?
+ @status == 200 && string_body?
+ end
+
+ def string_body?
+ !@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) }
+ end
+
+ DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
+
+ def set_conditional_cache_control!
+ control = @cache_control
+
+ if control.empty?
+ headers["Cache-Control"] = DEFAULT_CACHE_CONTROL
+ elsif @cache_control[:no_cache]
+ headers["Cache-Control"] = "no-cache"
+ else
+ extras = control[:extras]
+ max_age = control[:max_age]
+
+ options = []
+ options << "max-age=#{max_age.to_i}" if max_age
+ options << (control[:public] ? "public" : "private")
+ options << "must-revalidate" if control[:must_revalidate]
+ options.concat(extras) if extras
+
+ headers["Cache-Control"] = options.join(", ")
+ end
+ end
+ end
+ end
+ end
+end
View
101 actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -0,0 +1,101 @@
+module ActionDispatch
+ module Http
+ module MimeNegotiation
+ # The MIME type of the HTTP request, such as Mime::XML.
+ #
+ # For backward compatibility, the post \format is extracted from the
+ # X-Post-Data-Format HTTP header if present.
+ def content_type
+ @env["action_dispatch.request.content_type"] ||= begin
+ if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
+ Mime::Type.lookup($1.strip.downcase)
+ else
+ nil
+ end
+ end
+ end
+
+ # Returns the accepted MIME type for the request.
+ def accepts
+ @env["action_dispatch.request.accepts"] ||= begin
+ header = @env['HTTP_ACCEPT'].to_s.strip
+
+ if header.empty?
+ [content_type]
+ else
+ Mime::Type.parse(header)
+ end
+ end
+ end
+
+ # Returns the Mime type for the \format used in the request.
+ #
+ # GET /posts/5.xml | request.format => Mime::XML
+ # GET /posts/5.xhtml | request.format => Mime::HTML
+ # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
+ #
+ def format(view_path = [])
+ formats.first
+ end
+
+ def formats
+ accept = @env['HTTP_ACCEPT']
+
+ @env["action_dispatch.request.formats"] ||=
+ if parameters[:format]
+ Array(Mime[parameters[:format]])
+ elsif xhr? || (accept && !accept.include?(?,))
+ accepts
+ else
+ [Mime::HTML]
+ end
+ end
+
+ # Sets the \format by string extension, which can be used to force custom formats
+ # that are not controlled by the extension.
+ #
+ # class ApplicationController < ActionController::Base
+ # before_filter :adjust_format_for_iphone
+ #
+ # private
+ # def adjust_format_for_iphone
+ # request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
+ # end
+ # end
+ def format=(extension)
+ parameters[:format] = extension.to_s
+ @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
+ end
+
+ # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
+ # If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
+ # otherwise.
+ def template_format
+ parameter_format = parameters[:format]
+
+ if parameter_format
+ parameter_format
+ elsif xhr?
+ :js
+ else
+ :html
+ end
+ end
+
+ # Receives an array of mimes and return the first user sent mime that
+ # matches the order array.
+ #
+ def negotiate_mime(order)
+ formats.each do |priority|
+ if priority == Mime::ALL
+ return order.first
+ elsif order.include?(priority)
+ return priority
+ end
+ end
+
+ order.include?(Mime::ALL) ? formats.first : nil
+ end
+ end
+ end
+end
View
50 actionpack/lib/action_dispatch/http/parameters.rb
@@ -0,0 +1,50 @@
+require 'active_support/core_ext/hash/keys'
+
+module ActionDispatch
+ module Http
+ module Parameters
+ # Returns both GET and POST \parameters in a single hash.
+ def parameters
+ @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
+ end
+ alias :params :parameters
+
+ def path_parameters=(parameters) #:nodoc:
+ @env.delete("action_dispatch.request.symbolized_path_parameters")
+ @env.delete("action_dispatch.request.parameters")
+ @env["action_dispatch.request.path_parameters"] = parameters
+ end
+
+ # The same as <tt>path_parameters</tt> with explicitly symbolized keys.
+ def symbolized_path_parameters
+ @env["action_dispatch.request.symbolized_path_parameters"] ||= path_parameters.symbolize_keys
+ end
+
+ # Returns a hash with the \parameters used to form the \path of the request.
+ # Returned hash keys are strings:
+ #
+ # {'action' => 'my_action', 'controller' => 'my_controller'}
+ #
+ # See <tt>symbolized_path_parameters</tt> for symbolized keys.
+ def path_parameters
+ @env["action_dispatch.request.path_parameters"] ||= {}
+ end
+
+ private
+
+ # Convert nested Hashs to HashWithIndifferentAccess
+ def normalize_parameters(value)
+ case value
+ when Hash
+ h = {}
+ value.each { |k, v| h[k] = normalize_parameters(v) }
+ h.with_indifferent_access
+ when Array
+ value.map { |e| normalize_parameters(e) }
+ else
+ value
+ end
+ end
+ end
+ end
+end
View
379 actionpack/lib/action_dispatch/http/request.rb
@@ -2,14 +2,17 @@
require 'stringio'
require 'strscan'
-require 'active_support/memoizable'
-require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/string/access'
require 'action_dispatch/http/headers'
module ActionDispatch
class Request < Rack::Request
+ include ActionDispatch::Http::Cache::Request
+ include ActionDispatch::Http::MimeNegotiation
+ include ActionDispatch::Http::Parameters
+ include ActionDispatch::Http::Upload
+ include ActionDispatch::Http::URL
%w[ AUTH_TYPE GATEWAY_INTERFACE
PATH_TRANSLATED REMOTE_HOST
@@ -19,9 +22,11 @@ class Request < Rack::Request
HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
HTTP_NEGOTIATE HTTP_PRAGMA ].each do |env|
- define_method(env.sub(/^HTTP_/n, '').downcase) do
- @env[env]
- end
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
+ def #{env.sub(/^HTTP_/n, '').downcase}
+ @env["#{env}"]
+ end
+ METHOD
end
def key?(key)
@@ -81,25 +86,6 @@ def headers
Http::Headers.new(@env)
end
- # Returns the content length of the request as an integer.
- def content_length
- super.to_i
- end
-
- # The MIME type of the HTTP request, such as Mime::XML.
- #
- # For backward compatibility, the post \format is extracted from the
- # X-Post-Data-Format HTTP header if present.
- def content_type
- @env["action_dispatch.request.content_type"] ||= begin
- if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
- Mime::Type.lookup($1.strip.downcase)
- else
- nil
- end
- end
- end
-
def forgery_whitelisted?
method == :get || xhr? || content_type.nil? || !content_type.verify_request?
end
@@ -108,104 +94,9 @@ def media_type
content_type.to_s
end
- # Returns the accepted MIME type for the request.
- def accepts
- @env["action_dispatch.request.accepts"] ||= begin
- header = @env['HTTP_ACCEPT'].to_s.strip
-
- if header.empty?
- [content_type]
- else
- Mime::Type.parse(header)
- end
- end
- end
-
- def if_modified_since
- if since = env['HTTP_IF_MODIFIED_SINCE']
- Time.rfc2822(since) rescue nil
- end
- end
-
- def if_none_match
- env['HTTP_IF_NONE_MATCH']
- end
-
- def not_modified?(modified_at)
- if_modified_since && modified_at && if_modified_since >= modified_at
- end
-
- def etag_matches?(etag)
- if_none_match && if_none_match == etag
- end
-
- # Check response freshness (Last-Modified and ETag) against request
- # If-Modified-Since and If-None-Match conditions. If both headers are
- # supplied, both must match, or the request is not considered fresh.
- def fresh?(response)
- last_modified = if_modified_since
- etag = if_none_match
-
- return false unless last_modified || etag
-
- success = true
- success &&= not_modified?(response.last_modified) if last_modified
- success &&= etag_matches?(response.etag) if etag
- success
- end
-
- # Returns the Mime type for the \format used in the request.
- #
- # GET /posts/5.xml | request.format => Mime::XML
- # GET /posts/5.xhtml | request.format => Mime::HTML
- # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
- #
- def format(view_path = [])
- formats.first
- end
-
- def formats
- accept = @env['HTTP_ACCEPT']
-
- @env["action_dispatch.request.formats"] ||=
- if parameters[:format]
- Array.wrap(Mime[parameters[:format]])
- elsif xhr? || (accept && !accept.include?(?,))
- accepts
- else
- [Mime::HTML]
- end
- end
-
- # Sets the \format by string extension, which can be used to force custom formats
- # that are not controlled by the extension.
- #
- # class ApplicationController < ActionController::Base
- # before_filter :adjust_format_for_iphone
- #
- # private
- # def adjust_format_for_iphone
- # request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
- # end
- # end
- def format=(extension)
- parameters[:format] = extension.to_s
- @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
- end
-
- # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
- # If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
- # otherwise.
- def template_format
- parameter_format = parameters[:format]
-
- if parameter_format
- parameter_format
- elsif xhr?
- :js
- else
- :html
- end
+ # Returns the content length of the request as an integer.
+ def content_length
+ super.to_i
end
# Returns true if the request's "X-Requested-With" header contains
@@ -238,7 +129,7 @@ def remote_ip
if @env.include? 'HTTP_CLIENT_IP'
if ActionController::Base.ip_spoofing_check && remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP'])
# We don't know which came from the proxy, and which from the user
- raise ActionController::ActionControllerError.new(<<EOM)
+ raise ActionController::ActionControllerError.new <<EOM
IP spoofing attack?!
HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}
HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}
@@ -264,124 +155,6 @@ def server_software
(@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
end
- # Returns the complete URL used for this request.
- def url
- protocol + host_with_port + request_uri
- end
-
- # Returns 'https://' if this is an SSL request and 'http://' otherwise.
- def protocol
- ssl? ? 'https://' : 'http://'
- end
-
- # Is this an SSL request?
- def ssl?
- @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
- end
-
- # Returns the \host for this request, such as "example.com".
- def raw_host_with_port
- if forwarded = env["HTTP_X_FORWARDED_HOST"]
- forwarded.split(/,\s?/).last
- else
- env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
- end
- end
-
- # Returns the host for this request, such as example.com.
- def host
- raw_host_with_port.sub(/:\d+$/, '')
- end
-
- # Returns a \host:\port string for this request, such as "example.com" or
- # "example.com:8080".
- def host_with_port
- "#{host}#{port_string}"
- end
-
- # Returns the port number of this request as an integer.
- def port
- if raw_host_with_port =~ /:(\d+)$/
- $1.to_i
- else
- standard_port
- end
- end
-
- # Returns the standard \port number for this request's protocol.
- def standard_port
- case protocol
- when 'https://' then 443
- else 80
- end
- end
-
- # Returns a \port suffix like ":8080" if the \port number of this request
- # is not the default HTTP \port 80 or HTTPS \port 443.
- def port_string
- port == standard_port ? '' : ":#{port}"
- end
-
- def server_port
- @env['SERVER_PORT'].to_i
- end
-
- # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
- # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
- def domain(tld_length = 1)
- return nil unless named_host?(host)
-
- host.split('.').last(1 + tld_length).join('.')
- end
-
- # Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
- # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
- # such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
- # in "www.rubyonrails.co.uk".
- def subdomains(tld_length = 1)
- return [] unless named_host?(host)
- parts = host.split('.')
- parts[0..-(tld_length+2)]
- end
-
- # Returns the query string, accounting for server idiosyncrasies.
- def query_string
- @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].to_s.split('?', 2)[1] || '')
- end
-
- # Returns the request URI, accounting for server idiosyncrasies.
- # WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
- def request_uri
- if uri = @env['REQUEST_URI']
- # Remove domain, which webrick puts into the request_uri.
- (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri
- else
- # Construct IIS missing REQUEST_URI from SCRIPT_NAME and PATH_INFO.
- uri = @env['PATH_INFO'].to_s
-
- if script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
- uri = uri.sub(/#{script_filename}\//, '')
- end
-
- env_qs = @env['QUERY_STRING'].to_s
- uri += "?#{env_qs}" unless env_qs.empty?
-
- if uri.blank?
- @env.delete('REQUEST_URI')
- else
- @env['REQUEST_URI'] = uri
- end
- end
- end
-
- # Returns the interpreted \path to requested resource after all the installation
- # directory of this application was taken into account.
- def path
- path = request_uri.to_s[/\A[^\?]*/]
- path.sub!(/\A#{ActionController::Base.relative_url_root}/, '')
- path
- end
-
# Read the request \body. This is useful for web services that need to
# work with raw requests directly.
def raw_post
@@ -392,33 +165,6 @@ def raw_post
@env['RAW_POST_DATA']
end
- # Returns both GET and POST \parameters in a single hash.
- def parameters
- @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
- end
- alias_method :params, :parameters
-
- def path_parameters=(parameters) #:nodoc:
- @env.delete("action_dispatch.request.symbolized_path_parameters")
- @env.delete("action_dispatch.request.parameters")
- @env["action_dispatch.request.path_parameters"] = parameters
- end
-
- # The same as <tt>path_parameters</tt> with explicitly symbolized keys.
- def symbolized_path_parameters
- @env["action_dispatch.request.symbolized_path_parameters"] ||= path_parameters.symbolize_keys
- end
-
- # Returns a hash with the \parameters used to form the \path of the request.
- # Returned hash keys are strings:
- #
- # {'action' => 'my_action', 'controller' => 'my_controller'}
- #
- # See <tt>symbolized_path_parameters</tt> for symbolized keys.
- def path_parameters
- @env["action_dispatch.request.path_parameters"] ||= {}
- end
-
# The request body is an IO input stream. If the RAW_POST_DATA environment
# variable is already set, wrap it in a StringIO.
def body
@@ -434,18 +180,6 @@ def form_data?
FORM_DATA_MEDIA_TYPES.include?(content_type.to_s)
end
- # Override Rack's GET method to support indifferent access
- def GET
- @env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super)
- end
- alias_method :query_parameters, :GET
-
- # Override Rack's POST method to support indifferent access
- def POST
- @env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super)
- end
- alias_method :request_parameters, :POST
-
def body_stream #:nodoc:
@env['rack.input']
end
@@ -463,6 +197,19 @@ def session_options=(options)
@env['rack.session.options'] = options
end
+ # Override Rack's GET method to support indifferent access
+ def GET
+ @env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super)
+ end
+ alias :query_parameters :GET
+
+ # Override Rack's POST method to support indifferent access
+ def POST
+ @env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super)
+ end
+ alias :request_parameters :POST
+
+
# Returns the authorization header regardless of whether it was specified directly or through one of the
# proxy alternatives.
def authorization
@@ -471,77 +218,5 @@ def authorization
@env['X_HTTP_AUTHORIZATION'] ||
@env['REDIRECT_X_HTTP_AUTHORIZATION']
end
-
- # Receives an array of mimes and return the first user sent mime that
- # matches the order array.
- #
- def negotiate_mime(order)
- formats.each do |priority|
- if priority == Mime::ALL
- return order.first
- elsif order.include?(priority)
- return priority
- end
- end
-
- order.include?(Mime::ALL) ? formats.first : nil
- end
-
- private
-
- def named_host?(host)
- !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
- end
-
- module UploadedFile
- def self.extended(object)
- object.class_eval do
- attr_accessor :original_path, :content_type
- alias_method :local_path, :path if method_defined?(:path)
- end
- end
-
- # Take the basename of the upload's original filename.
- # This handles the full Windows paths given by Internet Explorer
- # (and perhaps other broken user agents) without affecting
- # those which give the lone filename.
- # The Windows regexp is adapted from Perl's File::Basename.
- def original_filename
- unless defined? @original_filename
- @original_filename =
- unless original_path.blank?
- if original_path =~ /^(?:.*[:\\\/])?(.*)/m
- $1
- else
- File.basename original_path
- end
- end
- end
- @original_filename
- end
- end
-
- # Convert nested Hashs to HashWithIndifferentAccess and replace
- # file upload hashs with UploadedFile objects
- def normalize_parameters(value)
- case value
- when Hash
- if value.has_key?(:tempfile)
- upload = value[:tempfile]
- upload.extend(UploadedFile)
- upload.original_path = value[:filename]
- upload.content_type = value[:type]
- upload
- else
- h = {}
- value.each { |k, v| h[k] = normalize_parameters(v) }
- h.with_indifferent_access
- end
- when Array
- value.map { |e| normalize_parameters(e) }
- else
- value
- end
- end
end
end
View
82 actionpack/lib/action_dispatch/http/response.rb
@@ -32,6 +32,8 @@ module ActionDispatch # :nodoc:
# end
# end
class Response < Rack::Response
+ include ActionDispatch::Http::Cache::Response
+
attr_accessor :request, :blank
attr_writer :header, :sending_file
@@ -55,10 +57,6 @@ def initialize
yield self if block_given?
end
- def cache_control
- @cache_control ||= {}
- end
-
def status=(status)
@status = Rack::Utils.status_code(status)
end
@@ -114,33 +112,6 @@ def location=(url)
# information.
attr_accessor :charset, :content_type
- def last_modified
- if last = headers['Last-Modified']
- Time.httpdate(last)
- end
- end
-
- def last_modified?
- headers.include?('Last-Modified')
- end
-
- def last_modified=(utc_time)
- headers['Last-Modified'] = utc_time.httpdate
- end
-
- def etag
- @etag
- end
-
- def etag?
- @etag
- end
-
- def etag=(etag)
- key = ActiveSupport::Cache.expand_cache_key(etag)
- @etag = %("#{Digest::MD5.hexdigest(key)}")
- end
-
CONTENT_TYPE = "Content-Type"
cattr_accessor(:default_charset) { "utf-8" }
@@ -148,7 +119,7 @@ def etag=(etag)
def to_a
assign_default_content_type_and_charset!
handle_conditional_get!
- self["Set-Cookie"] = @cookie.join("\n")
+ self["Set-Cookie"] = @cookie.join("\n") unless @cookie.blank?
self["ETag"] = @etag if @etag
super
end
@@ -222,31 +193,6 @@ def delete_cookie(key, value={})
end
private
- def handle_conditional_get!
- if etag? || last_modified? || !@cache_control.empty?
- set_conditional_cache_control!
- elsif nonempty_ok_response?
- self.etag = @body
-
- if request && request.etag_matches?(etag)
- self.status = 304
- self.body = []
- end
-
- set_conditional_cache_control!
- else
- headers["Cache-Control"] = "no-cache"
- end
- end
-
- def nonempty_ok_response?
- @status == 200 && string_body?
- end
-
- def string_body?
- !@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) }
- end
-
def assign_default_content_type_and_charset!
return if headers[CONTENT_TYPE].present?
@@ -259,27 +205,5 @@ def assign_default_content_type_and_charset!
headers[CONTENT_TYPE] = type
end
- DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
-
- def set_conditional_cache_control!
- control = @cache_control
-
- if control.empty?
- headers["Cache-Control"] = DEFAULT_CACHE_CONTROL
- elsif @cache_control[:no_cache]
- headers["Cache-Control"] = "no-cache"
- else
- extras = control[:extras]
- max_age = control[:max_age]
-
- options = []
- options << "max-age=#{max_age.to_i}" if max_age
- options << (control[:public] ? "public" : "private")
- options << "must-revalidate" if control[:must_revalidate]
- options.concat(extras) if extras
-
- headers["Cache-Control"] = options.join(", ")
- end
- end
end
end
View
48 actionpack/lib/action_dispatch/http/upload.rb
@@ -0,0 +1,48 @@
+module ActionDispatch
+ module Http
+ module UploadedFile
+ def self.extended(object)
+ object.class_eval do
+ attr_accessor :original_path, :content_type
+ alias_method :local_path, :path if method_defined?(:path)
+ end
+ end
+
+ # Take the basename of the upload's original filename.
+ # This handles the full Windows paths given by Internet Explorer
+ # (and perhaps other broken user agents) without affecting
+ # those which give the lone filename.
+ # The Windows regexp is adapted from Perl's File::Basename.
+ def original_filename
+ unless defined? @original_filename
+ @original_filename =
+ unless original_path.blank?
+ if original_path =~ /^(?:.*[:\\\/])?(.*)/m
+ $1
+ else
+ File.basename original_path
+ end
+ end
+ end
+ @original_filename
+ end
+ end
+
+ module Upload
+ # Convert nested Hashs to HashWithIndifferentAccess and replace
+ # file upload hashs with UploadedFile objects
+ def normalize_parameters(value)
+ if Hash === value && value.has_key?(:tempfile)
+ upload = value[:tempfile]
+ upload.extend(UploadedFile)
+ upload.original_path = value[:filename]
+ upload.content_type = value[:type]
+ upload
+ else
+ super
+ end
+ end
+ private :normalize_parameters
+ end
+ end
+end
View
129 actionpack/lib/action_dispatch/http/url.rb
@@ -0,0 +1,129 @@
+module ActionDispatch
+ module Http
+ module URL
+ # Returns the complete URL used for this request.
+ def url
+ protocol + host_with_port + request_uri
+ end
+
+ # Returns 'https://' if this is an SSL request and 'http://' otherwise.
+ def protocol
+ ssl? ? 'https://' : 'http://'
+ end
+
+ # Is this an SSL request?
+ def ssl?
+ @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
+ end
+
+ # Returns the \host for this request, such as "example.com".
+ def raw_host_with_port
+ if forwarded = env["HTTP_X_FORWARDED_HOST"]
+ forwarded.split(/,\s?/).last
+ else
+ env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
+ end
+ end
+
+ # Returns the host for this request, such as example.com.
+ def host
+ raw_host_with_port.sub(/:\d+$/, '')
+ end
+
+ # Returns a \host:\port string for this request, such as "example.com" or
+ # "example.com:8080".
+ def host_with_port
+ "#{host}#{port_string}"
+ end
+
+ # Returns the port number of this request as an integer.
+ def port
+ if raw_host_with_port =~ /:(\d+)$/
+ $1.to_i
+ else
+ standard_port
+ end
+ end
+
+ # Returns the standard \port number for this request's protocol.
+ def standard_port
+ case protocol
+ when 'https://' then 443
+ else 80
+ end
+ end
+
+ # Returns a \port suffix like ":8080" if the \port number of this request
+ # is not the default HTTP \port 80 or HTTPS \port 443.
+ def port_string
+ port == standard_port ? '' : ":#{port}"
+ end
+
+ def server_port
+ @env['SERVER_PORT'].to_i
+ end
+
+ # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
+ # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
+ def domain(tld_length = 1)
+ return nil unless named_host?(host)
+
+ host.split('.').last(1 + tld_length).join('.')
+ end
+
+ # Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
+ # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
+ # such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
+ # in "www.rubyonrails.co.uk".
+ def subdomains(tld_length = 1)
+ return [] unless named_host?(host)
+ parts = host.split('.')
+ parts[0..-(tld_length+2)]
+ end
+
+ # Returns the query string, accounting for server idiosyncrasies.
+ def query_string
+ @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].to_s.split('?', 2)[1] || '')
+ end
+
+ # Returns the request URI, accounting for server idiosyncrasies.
+ # WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
+ def request_uri
+ if uri = @env['REQUEST_URI']
+ # Remove domain, which webrick puts into the request_uri.
+ (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri
+ else
+ # Construct IIS missing REQUEST_URI from SCRIPT_NAME and PATH_INFO.
+ uri = @env['PATH_INFO'].to_s
+
+ if script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
+ uri = uri.sub(/#{script_filename}\//, '')
+ end
+
+ env_qs = @env['QUERY_STRING'].to_s
+ uri += "?#{env_qs}" unless env_qs.empty?
+
+ if uri.blank?
+ @env.delete('REQUEST_URI')
+ else
+ @env['REQUEST_URI'] = uri
+ end
+ end
+ end
+
+ # Returns the interpreted \path to requested resource after all the installation
+ # directory of this application was taken into account.
+ def path
+ path = request_uri.to_s[/\A[^\?]*/]
+ path.sub!(/\A#{ActionController::Base.relative_url_root}/, '')
+ path
+ end
+
+ private
+
+ def named_host?(host)
+ !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
+ end
+ end
+ end
+end
View
2  actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -45,8 +45,6 @@ def call(env)
run_callbacks(:prepare) if @prepare_each_request
@app.call(env)
end
- ensure
- ActiveSupport::Notifications.instrument "action_dispatch.callback"
end
end
end
View
216 actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -0,0 +1,216 @@
+module ActionDispatch
+ class Request
+ def cookie_jar
+ env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self)
+ end
+ end
+
+ # Cookies are read and written through ActionController#cookies.
+ #
+ # The cookies being read are the ones received along with the request, the cookies
+ # being written will be sent out with the response. Reading a cookie does not get
+ # the cookie object itself back, just the value it holds.
+ #
+ # Examples for writing:
+ #
+ # # Sets a simple session cookie.
+ # cookies[:user_name] = "david"
+ #
+ # #