actionpack 3.2.22.5 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +641 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller.rb +1 -8
  6. data/lib/abstract_controller/asset_paths.rb +2 -2
  7. data/lib/abstract_controller/base.rb +39 -37
  8. data/lib/abstract_controller/callbacks.rb +101 -82
  9. data/lib/abstract_controller/collector.rb +7 -3
  10. data/lib/abstract_controller/helpers.rb +23 -11
  11. data/lib/abstract_controller/layouts.rb +68 -73
  12. data/lib/abstract_controller/logger.rb +1 -2
  13. data/lib/abstract_controller/rendering.rb +22 -13
  14. data/lib/abstract_controller/translation.rb +16 -1
  15. data/lib/abstract_controller/url_for.rb +6 -6
  16. data/lib/abstract_controller/view_paths.rb +1 -1
  17. data/lib/action_controller.rb +15 -6
  18. data/lib/action_controller/base.rb +46 -22
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/caching/fragments.rb +23 -53
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  23. data/lib/action_controller/log_subscriber.rb +11 -8
  24. data/lib/action_controller/metal.rb +16 -30
  25. data/lib/action_controller/metal/conditional_get.rb +76 -32
  26. data/lib/action_controller/metal/data_streaming.rb +20 -26
  27. data/lib/action_controller/metal/exceptions.rb +19 -6
  28. data/lib/action_controller/metal/flash.rb +24 -9
  29. data/lib/action_controller/metal/force_ssl.rb +32 -9
  30. data/lib/action_controller/metal/head.rb +25 -4
  31. data/lib/action_controller/metal/helpers.rb +6 -9
  32. data/lib/action_controller/metal/hide_actions.rb +1 -2
  33. data/lib/action_controller/metal/http_authentication.rb +105 -87
  34. data/lib/action_controller/metal/implicit_render.rb +1 -1
  35. data/lib/action_controller/metal/instrumentation.rb +2 -1
  36. data/lib/action_controller/metal/live.rb +141 -0
  37. data/lib/action_controller/metal/mime_responds.rb +161 -47
  38. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  39. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  40. data/lib/action_controller/metal/redirecting.rb +15 -20
  41. data/lib/action_controller/metal/renderers.rb +11 -9
  42. data/lib/action_controller/metal/rendering.rb +8 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  44. data/lib/action_controller/metal/responder.rb +20 -19
  45. data/lib/action_controller/metal/streaming.rb +12 -18
  46. data/lib/action_controller/metal/strong_parameters.rb +516 -0
  47. data/lib/action_controller/metal/testing.rb +13 -18
  48. data/lib/action_controller/metal/url_for.rb +27 -25
  49. data/lib/action_controller/model_naming.rb +12 -0
  50. data/lib/action_controller/railtie.rb +33 -17
  51. data/lib/action_controller/railties/helpers.rb +22 -0
  52. data/lib/action_controller/record_identifier.rb +18 -72
  53. data/lib/action_controller/test_case.rb +215 -123
  54. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  55. data/lib/action_dispatch.rb +27 -19
  56. data/lib/action_dispatch/http/cache.rb +63 -11
  57. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  59. data/lib/action_dispatch/http/headers.rb +27 -19
  60. data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
  61. data/lib/action_dispatch/http/mime_type.rb +145 -113
  62. data/lib/action_dispatch/http/mime_types.rb +1 -1
  63. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  64. data/lib/action_dispatch/http/parameters.rb +12 -5
  65. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  66. data/lib/action_dispatch/http/request.rb +49 -18
  67. data/lib/action_dispatch/http/response.rb +129 -35
  68. data/lib/action_dispatch/http/upload.rb +60 -17
  69. data/lib/action_dispatch/http/url.rb +53 -31
  70. data/lib/action_dispatch/journey.rb +5 -0
  71. data/lib/action_dispatch/journey/backwards.rb +5 -0
  72. data/lib/action_dispatch/journey/formatter.rb +146 -0
  73. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  74. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  75. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  76. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  77. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  78. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  79. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  80. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  81. data/lib/action_dispatch/journey/parser.rb +206 -0
  82. data/lib/action_dispatch/journey/parser.y +47 -0
  83. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  84. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  85. data/lib/action_dispatch/journey/route.rb +116 -0
  86. data/lib/action_dispatch/journey/router.rb +164 -0
  87. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  88. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  89. data/lib/action_dispatch/journey/routes.rb +75 -0
  90. data/lib/action_dispatch/journey/scanner.rb +61 -0
  91. data/lib/action_dispatch/journey/visitors.rb +189 -0
  92. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  93. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  94. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  95. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  96. data/lib/action_dispatch/middleware/cookies.rb +168 -57
  97. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
  99. data/lib/action_dispatch/middleware/flash.rb +58 -58
  100. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
  102. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  103. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  104. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  110. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  111. data/lib/action_dispatch/middleware/stack.rb +6 -1
  112. data/lib/action_dispatch/middleware/static.rb +5 -24
  113. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  114. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  116. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  117. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  122. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  123. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  124. data/lib/action_dispatch/railtie.rb +16 -6
  125. data/lib/action_dispatch/request/session.rb +181 -0
  126. data/lib/action_dispatch/routing.rb +41 -40
  127. data/lib/action_dispatch/routing/inspector.rb +240 -0
  128. data/lib/action_dispatch/routing/mapper.rb +501 -273
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  130. data/lib/action_dispatch/routing/redirection.rb +46 -29
  131. data/lib/action_dispatch/routing/route_set.rb +203 -164
  132. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  133. data/lib/action_dispatch/routing/url_for.rb +48 -33
  134. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  135. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  136. data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
  137. data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
  138. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  139. data/lib/action_dispatch/testing/integration.rb +41 -22
  140. data/lib/action_dispatch/testing/test_process.rb +9 -6
  141. data/lib/action_dispatch/testing/test_request.rb +7 -3
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_pack/version.rb +4 -4
  144. data/lib/action_view.rb +17 -8
  145. data/lib/action_view/base.rb +15 -34
  146. data/lib/action_view/buffers.rb +1 -1
  147. data/lib/action_view/context.rb +4 -4
  148. data/lib/action_view/dependency_tracker.rb +91 -0
  149. data/lib/action_view/digestor.rb +85 -0
  150. data/lib/action_view/flows.rb +1 -4
  151. data/lib/action_view/helpers.rb +2 -4
  152. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  153. data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
  154. data/lib/action_view/helpers/asset_url_helper.rb +354 -0
  155. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  156. data/lib/action_view/helpers/cache_helper.rb +150 -18
  157. data/lib/action_view/helpers/capture_helper.rb +42 -29
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  159. data/lib/action_view/helpers/date_helper.rb +268 -247
  160. data/lib/action_view/helpers/debug_helper.rb +10 -11
  161. data/lib/action_view/helpers/form_helper.rb +904 -547
  162. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  163. data/lib/action_view/helpers/form_tag_helper.rb +188 -88
  164. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  165. data/lib/action_view/helpers/number_helper.rb +148 -354
  166. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  167. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  168. data/lib/action_view/helpers/rendering_helper.rb +2 -4
  169. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  170. data/lib/action_view/helpers/tag_helper.rb +43 -37
  171. data/lib/action_view/helpers/tags.rb +39 -0
  172. data/lib/action_view/helpers/tags/base.rb +148 -0
  173. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  174. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  175. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  176. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  177. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  178. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  179. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  180. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  181. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  182. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  183. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  184. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  185. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  186. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  187. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  188. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  189. data/lib/action_view/helpers/tags/label.rb +65 -0
  190. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  191. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  192. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  193. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  194. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  195. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  196. data/lib/action_view/helpers/tags/select.rb +41 -0
  197. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  198. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  199. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  200. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  201. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  202. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  203. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  204. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  205. data/lib/action_view/helpers/text_helper.rb +126 -113
  206. data/lib/action_view/helpers/translation_helper.rb +32 -16
  207. data/lib/action_view/helpers/url_helper.rb +200 -271
  208. data/lib/action_view/locale/en.yml +1 -105
  209. data/lib/action_view/log_subscriber.rb +6 -4
  210. data/lib/action_view/lookup_context.rb +15 -39
  211. data/lib/action_view/model_naming.rb +12 -0
  212. data/lib/action_view/path_set.rb +9 -39
  213. data/lib/action_view/railtie.rb +6 -22
  214. data/lib/action_view/record_identifier.rb +84 -0
  215. data/lib/action_view/renderer/abstract_renderer.rb +10 -19
  216. data/lib/action_view/renderer/partial_renderer.rb +144 -81
  217. data/lib/action_view/renderer/renderer.rb +2 -19
  218. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  219. data/lib/action_view/renderer/template_renderer.rb +14 -13
  220. data/lib/action_view/routing_url_for.rb +107 -0
  221. data/lib/action_view/template.rb +22 -21
  222. data/lib/action_view/template/error.rb +22 -12
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/handlers/builder.rb +1 -1
  225. data/lib/action_view/template/handlers/erb.rb +11 -16
  226. data/lib/action_view/template/handlers/raw.rb +11 -0
  227. data/lib/action_view/template/resolver.rb +111 -83
  228. data/lib/action_view/template/text.rb +12 -8
  229. data/lib/action_view/template/types.rb +57 -0
  230. data/lib/action_view/test_case.rb +66 -43
  231. data/lib/action_view/testing/resolvers.rb +3 -2
  232. data/lib/action_view/vendor/html-scanner.rb +20 -0
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  235. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
  236. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
  237. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  238. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  239. metadata +135 -125
  240. data/lib/action_controller/caching/actions.rb +0 -185
  241. data/lib/action_controller/caching/pages.rb +0 -187
  242. data/lib/action_controller/caching/sweeping.rb +0 -97
  243. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  244. data/lib/action_controller/metal/compatibility.rb +0 -65
  245. data/lib/action_controller/metal/session_management.rb +0 -14
  246. data/lib/action_controller/railties/paths.rb +0 -25
  247. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  248. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  249. data/lib/action_dispatch/middleware/head.rb +0 -18
  250. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  251. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  252. data/lib/action_view/asset_paths.rb +0 -142
  253. data/lib/action_view/helpers/asset_paths.rb +0 -7
  254. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  255. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  256. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  257. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  258. data/lib/sprockets/assets.rake +0 -99
  259. data/lib/sprockets/bootstrap.rb +0 -37
  260. data/lib/sprockets/compressors.rb +0 -83
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  263. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  264. data/lib/sprockets/railtie.rb +0 -62
  265. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,9 +1,8 @@
1
- require 'active_support/core_ext/class/attribute'
2
1
  require 'active_support/core_ext/hash/slice'
3
2
  require 'active_support/core_ext/hash/except'
4
- require 'active_support/core_ext/array/wrap'
5
3
  require 'active_support/core_ext/module/anonymous'
6
- require 'action_dispatch/http/mime_types'
4
+ require 'active_support/core_ext/struct'
5
+ require 'action_dispatch/http/mime_type'
7
6
 
8
7
  module ActionController
9
8
  # Wraps the parameters hash into a nested hash. This will allow clients to submit
@@ -17,7 +16,7 @@ module ActionController
17
16
  # a non-empty array:
18
17
  #
19
18
  # class UsersController < ApplicationController
20
- # wrap_parameters :format => [:json, :xml]
19
+ # wrap_parameters format: [:json, :xml]
21
20
  # end
22
21
  #
23
22
  # If you enable +ParamsWrapper+ for +:json+ format, instead of having to
@@ -40,16 +39,15 @@ module ActionController
40
39
  # +:exclude+ options like this:
41
40
  #
42
41
  # class UsersController < ApplicationController
43
- # wrap_parameters :person, :include => [:username, :password]
42
+ # wrap_parameters :person, include: [:username, :password]
44
43
  # end
45
44
  #
46
- # On ActiveRecord models with no +:include+ or +:exclude+ option set,
47
- # if attr_accessible is set on that model, it will only wrap the accessible
48
- # parameters, else it will only wrap the parameters returned by the class
49
- # method attribute_names.
45
+ # On ActiveRecord models with no +:include+ or +:exclude+ option set,
46
+ # it will only wrap the parameters returned by the class method
47
+ # <tt>attribute_names</tt>.
50
48
  #
51
49
  # If you're going to pass the parameters to an +ActiveModel+ object (such as
52
- # +User.new(params[:user])+), you might consider passing the model class to
50
+ # <tt>User.new(params[:user])</tt>), you might consider passing the model class to
53
51
  # the method instead. The +ParamsWrapper+ will actually try to determine the
54
52
  # list of attribute names from the model and only wrap those attributes:
55
53
  #
@@ -67,7 +65,7 @@ module ActionController
67
65
  # class Admin::UsersController < ApplicationController
68
66
  # end
69
67
  #
70
- # will try to check if +Admin::User+ or +User+ model exists, and use it to
68
+ # will try to check if <tt>Admin::User</tt> or +User+ model exists, and use it to
71
69
  # determine the wrapper key respectively. If both models don't exist,
72
70
  # it will then fallback to use +user+ as the key.
73
71
  module ParamsWrapper
@@ -75,17 +73,104 @@ module ActionController
75
73
 
76
74
  EXCLUDE_PARAMETERS = %w(authenticity_token _method utf8)
77
75
 
76
+ require 'mutex_m'
77
+
78
+ class Options < Struct.new(:name, :format, :include, :exclude, :klass, :model) # :nodoc:
79
+ include Mutex_m
80
+
81
+ def self.from_hash(hash)
82
+ name = hash[:name]
83
+ format = Array(hash[:format])
84
+ include = hash[:include] && Array(hash[:include]).collect(&:to_s)
85
+ exclude = hash[:exclude] && Array(hash[:exclude]).collect(&:to_s)
86
+ new name, format, include, exclude, nil, nil
87
+ end
88
+
89
+ def initialize(name, format, include, exclude, klass, model) # nodoc
90
+ super
91
+ @include_set = include
92
+ @name_set = name
93
+ end
94
+
95
+ def model
96
+ super || synchronize { super || self.model = _default_wrap_model }
97
+ end
98
+
99
+ def include
100
+ return super if @include_set
101
+
102
+ m = model
103
+ synchronize do
104
+ return super if @include_set
105
+
106
+ @include_set = true
107
+
108
+ unless super || exclude
109
+ if m.respond_to?(:attribute_names) && m.attribute_names.any?
110
+ self.include = m.attribute_names
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ def name
117
+ return super if @name_set
118
+
119
+ m = model
120
+ synchronize do
121
+ return super if @name_set
122
+
123
+ @name_set = true
124
+
125
+ unless super || klass.anonymous?
126
+ self.name = m ? m.to_s.demodulize.underscore :
127
+ klass.controller_name.singularize
128
+ end
129
+ end
130
+ end
131
+
132
+ private
133
+ # Determine the wrapper model from the controller's name. By convention,
134
+ # this could be done by trying to find the defined model that has the
135
+ # same singularize name as the controller. For example, +UsersController+
136
+ # will try to find if the +User+ model exists.
137
+ #
138
+ # This method also does namespace lookup. Foo::Bar::UsersController will
139
+ # try to find Foo::Bar::User, Foo::User and finally User.
140
+ def _default_wrap_model #:nodoc:
141
+ return nil if klass.anonymous?
142
+ model_name = klass.name.sub(/Controller$/, '').classify
143
+
144
+ begin
145
+ if model_klass = model_name.safe_constantize
146
+ model_klass
147
+ else
148
+ namespaces = model_name.split("::")
149
+ namespaces.delete_at(-2)
150
+ break if namespaces.last == model_name
151
+ model_name = namespaces.join("::")
152
+ end
153
+ end until model_klass
154
+
155
+ model_klass
156
+ end
157
+ end
158
+
78
159
  included do
79
160
  class_attribute :_wrapper_options
80
- self._wrapper_options = { :format => [] }
161
+ self._wrapper_options = Options.from_hash(format: [])
81
162
  end
82
163
 
83
164
  module ClassMethods
165
+ def _set_wrapper_options(options)
166
+ self._wrapper_options = Options.from_hash(options)
167
+ end
168
+
84
169
  # Sets the name of the wrapper key, or the model which +ParamsWrapper+
85
170
  # would use to determine the attribute names from.
86
171
  #
87
172
  # ==== Examples
88
- # wrap_parameters :format => :xml
173
+ # wrap_parameters format: :xml
89
174
  # # enables the parameter wrapper for XML format
90
175
  #
91
176
  # wrap_parameters :person
@@ -95,7 +180,7 @@ module ActionController
95
180
  # # wraps parameters by determining the wrapper key from Person class
96
181
  # (+person+, in this case) and the list of attribute names
97
182
  #
98
- # wrap_parameters :include => [:username, :title]
183
+ # wrap_parameters include: [:username, :title]
99
184
  # # wraps only +:username+ and +:title+ attributes from parameters.
100
185
  #
101
186
  # wrap_parameters false
@@ -122,71 +207,24 @@ module ActionController
122
207
  model = name_or_model_or_options
123
208
  end
124
209
 
125
- _set_wrapper_defaults(_wrapper_options.slice(:format).merge(options), model)
210
+ opts = Options.from_hash _wrapper_options.to_h.slice(:format).merge(options)
211
+ opts.model = model
212
+ opts.klass = self
213
+
214
+ self._wrapper_options = opts
126
215
  end
127
216
 
128
217
  # Sets the default wrapper key or model which will be used to determine
129
218
  # wrapper key and attribute names. Will be called automatically when the
130
219
  # module is inherited.
131
220
  def inherited(klass)
132
- if klass._wrapper_options[:format].present?
133
- klass._set_wrapper_defaults(klass._wrapper_options.slice(:format))
221
+ if klass._wrapper_options.format.any?
222
+ params = klass._wrapper_options.dup
223
+ params.klass = klass
224
+ klass._wrapper_options = params
134
225
  end
135
226
  super
136
227
  end
137
-
138
- protected
139
-
140
- # Determine the wrapper model from the controller's name. By convention,
141
- # this could be done by trying to find the defined model that has the
142
- # same singularize name as the controller. For example, +UsersController+
143
- # will try to find if the +User+ model exists.
144
- #
145
- # This method also does namespace lookup. Foo::Bar::UsersController will
146
- # try to find Foo::Bar::User, Foo::User and finally User.
147
- def _default_wrap_model #:nodoc:
148
- return nil if self.anonymous?
149
- model_name = self.name.sub(/Controller$/, '').classify
150
-
151
- begin
152
- if model_klass = model_name.safe_constantize
153
- model_klass
154
- else
155
- namespaces = model_name.split("::")
156
- namespaces.delete_at(-2)
157
- break if namespaces.last == model_name
158
- model_name = namespaces.join("::")
159
- end
160
- end until model_klass
161
-
162
- model_klass
163
- end
164
-
165
- def _set_wrapper_defaults(options, model=nil)
166
- options = options.dup
167
-
168
- unless options[:include] || options[:exclude]
169
- model ||= _default_wrap_model
170
- role = options.has_key?(:as) ? options[:as] : :default
171
- if model.respond_to?(:accessible_attributes) && model.accessible_attributes(role).present?
172
- options[:include] = model.accessible_attributes(role).to_a
173
- elsif model.respond_to?(:attribute_names) && model.attribute_names.present?
174
- options[:include] = model.attribute_names
175
- end
176
- end
177
-
178
- unless options[:name] || self.anonymous?
179
- model ||= _default_wrap_model
180
- options[:name] = model ? model.to_s.demodulize.underscore :
181
- controller_name.singularize
182
- end
183
-
184
- options[:include] = Array.wrap(options[:include]).collect(&:to_s) if options[:include]
185
- options[:exclude] = Array.wrap(options[:exclude]).collect(&:to_s) if options[:exclude]
186
- options[:format] = Array.wrap(options[:format])
187
-
188
- self._wrapper_options = options
189
- end
190
228
  end
191
229
 
192
230
  # Performs parameters wrapping upon the request. Will be called automatically
@@ -211,20 +249,20 @@ module ActionController
211
249
 
212
250
  # Returns the wrapper key which will use to stored wrapped parameters.
213
251
  def _wrapper_key
214
- _wrapper_options[:name]
252
+ _wrapper_options.name
215
253
  end
216
254
 
217
255
  # Returns the list of enabled formats.
218
256
  def _wrapper_formats
219
- _wrapper_options[:format]
257
+ _wrapper_options.format
220
258
  end
221
259
 
222
260
  # Returns the list of parameters which will be selected for wrapped.
223
261
  def _wrap_parameters(parameters)
224
- value = if include_only = _wrapper_options[:include]
262
+ value = if include_only = _wrapper_options.include
225
263
  parameters.slice(*include_only)
226
264
  else
227
- exclude = _wrapper_options[:exclude] || []
265
+ exclude = _wrapper_options.exclude || []
228
266
  parameters.except(*(exclude + EXCLUDE_PARAMETERS))
229
267
  end
230
268
 
@@ -8,9 +8,8 @@ module ActionController
8
8
  delegate :headers, :status=, :location=, :content_type=,
9
9
  :status, :location, :content_type, :to => "@_response"
10
10
 
11
- def dispatch(action, request, response = ActionDispatch::Response.new)
12
- @_response ||= response
13
- @_response.request ||= request
11
+ def dispatch(action, request)
12
+ set_response!(request)
14
13
  super(action, request)
15
14
  end
16
15
 
@@ -22,5 +21,12 @@ module ActionController
22
21
  def reset_session
23
22
  @_request.reset_session
24
23
  end
24
+
25
+ private
26
+
27
+ def set_response!(request)
28
+ @_response = ActionDispatch::Response.new
29
+ @_response.request = request
30
+ end
25
31
  end
26
32
  end
@@ -24,8 +24,7 @@ module ActionController
24
24
  # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.
25
25
  # Short-hand for <tt>redirect_to(request.env["HTTP_REFERER"])</tt>
26
26
  #
27
- # Examples:
28
- # redirect_to :action => "show", :id => 5
27
+ # redirect_to action: "show", id: 5
29
28
  # redirect_to post
30
29
  # redirect_to "http://www.rubyonrails.org"
31
30
  # redirect_to "/images/screenshot.jpg"
@@ -33,13 +32,12 @@ module ActionController
33
32
  # redirect_to :back
34
33
  # redirect_to proc { edit_post_url(@post) }
35
34
  #
36
- # The redirection happens as a "302 Moved" header unless otherwise specified.
35
+ # The redirection happens as a "302 Found" header unless otherwise specified.
37
36
  #
38
- # Examples:
39
- # redirect_to post_url(@post), :status => :found
40
- # redirect_to :action=>'atom', :status => :moved_permanently
41
- # redirect_to post_url(@post), :status => 301
42
- # redirect_to :action=>'atom', :status => 302
37
+ # redirect_to post_url(@post), status: :found
38
+ # redirect_to action: 'atom', status: :moved_permanently
39
+ # redirect_to post_url(@post), status: 301
40
+ # redirect_to action: 'atom', status: 302
43
41
  #
44
42
  # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
45
43
  # integer, or a symbol representing the downcased, underscored and symbolized description.
@@ -51,18 +49,16 @@ module ActionController
51
49
  # around this you can return a <tt>303 See Other</tt> status code which will be
52
50
  # followed using a GET request.
53
51
  #
54
- # Examples:
55
- # redirect_to posts_url, :status => :see_other
56
- # redirect_to :action => 'index', :status => 303
52
+ # redirect_to posts_url, status: :see_other
53
+ # redirect_to action: 'index', status: 303
57
54
  #
58
55
  # It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names
59
56
  # +alert+ and +notice+ as well as a general purpose +flash+ bucket.
60
57
  #
61
- # Examples:
62
- # redirect_to post_url(@post), :alert => "Watch it, mister!"
63
- # redirect_to post_url(@post), :status=> :found, :notice => "Pay attention to the road"
64
- # redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id }
65
- # redirect_to { :action=>'atom' }, :alert => "Something serious happened"
58
+ # redirect_to post_url(@post), alert: "Watch it, mister!"
59
+ # redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
60
+ # redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
61
+ # redirect_to { action: 'atom' }, alert: "Something serious happened"
66
62
  #
67
63
  # When using <tt>redirect_to :back</tt>, if there is no referrer, ActionController::RedirectBackError will be raised. You may specify some fallback
68
64
  # behavior for this case by rescuing ActionController::RedirectBackError.
@@ -92,18 +88,17 @@ module ActionController
92
88
  # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
93
89
  # characters; and is terminated by a colon (":").
94
90
  # The protocol relative scheme starts with a double slash "//"
95
- when %r{^(\w[\w+.-]*:|//).*}
91
+ when %r{\A(\w[\w+.-]*:|//).*}
96
92
  options
97
93
  when String
98
94
  request.protocol + request.host_with_port + options
99
95
  when :back
100
- raise RedirectBackError unless refer = request.headers["Referer"]
101
- refer
96
+ request.headers["Referer"] or raise RedirectBackError
102
97
  when Proc
103
98
  _compute_redirect_to_location options.call
104
99
  else
105
100
  url_for(options)
106
- end.gsub(/[\0\r\n]/, '')
101
+ end.delete("\0\r\n")
107
102
  end
108
103
  end
109
104
  end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/class/attribute'
2
- require 'active_support/core_ext/object/blank'
3
1
  require 'set'
4
2
 
5
3
  module ActionController
@@ -49,14 +47,13 @@ module ActionController
49
47
  # is the value paired with its key and the second is the remaining
50
48
  # hash of options passed to +render+.
51
49
  #
52
- # === Example
53
50
  # Create a csv renderer:
54
51
  #
55
52
  # ActionController::Renderers.add :csv do |obj, options|
56
53
  # filename = options[:filename] || 'data'
57
54
  # str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
58
- # send_data str, :type => Mime::CSV,
59
- # :disposition => "attachment; filename=#{filename}.csv"
55
+ # send_data str, type: Mime::CSV,
56
+ # disposition: "attachment; filename=#{filename}.csv"
60
57
  # end
61
58
  #
62
59
  # Note that we used Mime::CSV for the csv mime type as it comes with Rails.
@@ -69,7 +66,7 @@ module ActionController
69
66
  # @csvable = Csvable.find(params[:id])
70
67
  # respond_to do |format|
71
68
  # format.html
72
- # format.csv { render :csv => @csvable, :filename => @csvable.name }
69
+ # format.csv { render csv: @csvable, filename: @csvable.name }
73
70
  # }
74
71
  # end
75
72
  # To use renderers and their mime types in more concise ways, see
@@ -91,9 +88,14 @@ module ActionController
91
88
 
92
89
  add :json do |json, options|
93
90
  json = json.to_json(options) unless json.kind_of?(String)
94
- json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
95
- self.content_type ||= Mime::JSON
96
- json
91
+
92
+ if options[:callback].present?
93
+ self.content_type ||= Mime::JS
94
+ "#{options[:callback]}(#{json})"
95
+ else
96
+ self.content_type ||= Mime::JSON
97
+ json
98
+ end
97
99
  end
98
100
 
99
101
  add :js do |js, options|
@@ -29,6 +29,10 @@ module ActionController
29
29
  self.response_body = nil
30
30
  end
31
31
 
32
+ def render_to_body(*)
33
+ super || " "
34
+ end
35
+
32
36
  private
33
37
 
34
38
  # Normalize arguments by catching blocks and setting them on :update.
@@ -44,6 +48,10 @@ module ActionController
44
48
  options[:text] = options[:text].to_text
45
49
  end
46
50
 
51
+ if options.delete(:nothing) || (options.key?(:text) && options[:text].nil?)
52
+ options[:text] = " "
53
+ end
54
+
47
55
  if options[:status]
48
56
  options[:status] = Rack::Utils.status_code(options[:status])
49
57
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/class/attribute'
1
+ require 'rack/session/abstract/id'
2
2
  require 'action_controller/metal/exceptions'
3
3
 
4
4
  module ActionController #:nodoc:
@@ -14,10 +14,23 @@ module ActionController #:nodoc:
14
14
  # authentication scheme there anyway). Also, GET requests are not protected as these
15
15
  # should be idempotent.
16
16
  #
17
+ # It's important to remember that XML or JSON requests are also affected and if
18
+ # you're building an API you'll need something like:
19
+ #
20
+ # class ApplicationController < ActionController::Base
21
+ # protect_from_forgery
22
+ # skip_before_action :verify_authenticity_token, if: :json_request?
23
+ #
24
+ # protected
25
+ #
26
+ # def json_request?
27
+ # request.format.json?
28
+ # end
29
+ # end
30
+ #
17
31
  # CSRF protection is turned on with the <tt>protect_from_forgery</tt> method,
18
32
  # which checks the token and resets the session if it doesn't match what was expected.
19
33
  # A call to this method is generated for new \Rails applications by default.
20
- # You can customize the error message by editing public/422.html.
21
34
  #
22
35
  # The token parameter is named <tt>authenticity_token</tt> by default. The name and
23
36
  # value of this token must be added to every layout that renders forms by including
@@ -37,6 +50,10 @@ module ActionController #:nodoc:
37
50
  config_accessor :request_forgery_protection_token
38
51
  self.request_forgery_protection_token ||= :authenticity_token
39
52
 
53
+ # Holds the class which implements the request forgery protection.
54
+ config_accessor :forgery_protection_strategy
55
+ self.forgery_protection_strategy = nil
56
+
40
57
  # Controls whether request forgery protection is turned on or not. Turned off by default only in test mode.
41
58
  config_accessor :allow_forgery_protection
42
59
  self.allow_forgery_protection = true if allow_forgery_protection.nil?
@@ -48,50 +65,126 @@ module ActionController #:nodoc:
48
65
  module ClassMethods
49
66
  # Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
50
67
  #
51
- # Example:
52
- #
53
68
  # class FooController < ApplicationController
54
- # protect_from_forgery :except => :index
69
+ # protect_from_forgery except: :index
55
70
  #
56
71
  # You can disable csrf protection on controller-by-controller basis:
57
72
  #
58
- # skip_before_filter :verify_authenticity_token
73
+ # skip_before_action :verify_authenticity_token
59
74
  #
60
75
  # It can also be disabled for specific controller actions:
61
76
  #
62
- # skip_before_filter :verify_authenticity_token, :except => [:create]
77
+ # skip_before_action :verify_authenticity_token, except: [:create]
63
78
  #
64
79
  # Valid Options:
65
80
  #
66
- # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
81
+ # * <tt>:only/:except</tt> - Passed to the <tt>before_action</tt> call. Set which actions are verified.
82
+ # * <tt>:with</tt> - Set the method to handle unverified request.
83
+ #
84
+ # Valid unverified request handling methods are:
85
+ # * <tt>:exception</tt> - Raises ActionController::InvalidAuthenticityToken exception.
86
+ # * <tt>:reset_session</tt> - Resets the session.
87
+ # * <tt>:null_session</tt> - Provides an empty session during request but doesn't reset it completely. Used as default if <tt>:with</tt> option is not specified.
67
88
  def protect_from_forgery(options = {})
89
+ self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
68
90
  self.request_forgery_protection_token ||= :authenticity_token
69
- prepend_before_filter :verify_authenticity_token, options
91
+ prepend_before_action :verify_authenticity_token, options
92
+ end
93
+
94
+ private
95
+
96
+ def protection_method_class(name)
97
+ ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
98
+ rescue NameError
99
+ raise ArgumentError, 'Invalid request forgery protection method, use :null_session, :exception, or :reset_session'
100
+ end
101
+ end
102
+
103
+ module ProtectionMethods
104
+ class NullSession
105
+ def initialize(controller)
106
+ @controller = controller
107
+ end
108
+
109
+ # This is the method that defines the application behavior when a request is found to be unverified.
110
+ def handle_unverified_request
111
+ request = @controller.request
112
+ request.session = NullSessionHash.new(request.env)
113
+ request.env['action_dispatch.request.flash_hash'] = nil
114
+ request.env['rack.session.options'] = { skip: true }
115
+ request.env['action_dispatch.cookies'] = NullCookieJar.build(request)
116
+ end
117
+
118
+ protected
119
+
120
+ class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
121
+ def initialize(env)
122
+ super(nil, env)
123
+ @data = {}
124
+ @loaded = true
125
+ end
126
+
127
+ def exists?
128
+ true
129
+ end
130
+ end
131
+
132
+ class NullCookieJar < ActionDispatch::Cookies::CookieJar #:nodoc:
133
+ def self.build(request)
134
+ key_generator = request.env[ActionDispatch::Cookies::GENERATOR_KEY]
135
+ host = request.host
136
+ secure = request.ssl?
137
+
138
+ new(key_generator, host, secure, options_for_env({}))
139
+ end
140
+
141
+ def write(*)
142
+ # nothing
143
+ end
144
+ end
145
+ end
146
+
147
+ class ResetSession
148
+ def initialize(controller)
149
+ @controller = controller
150
+ end
151
+
152
+ def handle_unverified_request
153
+ @controller.reset_session
154
+ end
155
+ end
156
+
157
+ class Exception
158
+ def initialize(controller)
159
+ @controller = controller
160
+ end
161
+
162
+ def handle_unverified_request
163
+ raise ActionController::InvalidAuthenticityToken
164
+ end
70
165
  end
71
166
  end
72
167
 
73
168
  protected
74
- # The actual before_filter that is used. Modify this to change how you handle unverified requests.
169
+ def handle_unverified_request
170
+ forgery_protection_strategy.new(self).handle_unverified_request
171
+ end
172
+
173
+ # The actual before_action that is used. Modify this to change how you handle unverified requests.
75
174
  def verify_authenticity_token
76
175
  unless verified_request?
77
- logger.warn "WARNING: Can't verify CSRF token authenticity" if logger
176
+ logger.warn "Can't verify CSRF token authenticity" if logger
78
177
  handle_unverified_request
79
178
  end
80
179
  end
81
180
 
82
- # This is the method that defines the application behavior when a request is found to be unverified.
83
- # By default, \Rails resets the session when it finds an unverified request.
84
- def handle_unverified_request
85
- reset_session
86
- end
87
-
88
181
  # Returns true or false if a request is verified. Checks:
89
182
  #
90
- # * is it a GET request? Gets should be safe and idempotent
183
+ # * is it a GET or HEAD request? Gets should be safe and idempotent
91
184
  # * Does the form_authenticity_token match the given token value from the params?
92
185
  # * Does the X-CSRF-Token header match the form_authenticity_token
93
186
  def verified_request?
94
- !protect_against_forgery? || request.get? ||
187
+ !protect_against_forgery? || request.get? || request.head? ||
95
188
  form_authenticity_token == params[request_forgery_protection_token] ||
96
189
  form_authenticity_token == request.headers['X-CSRF-Token']
97
190
  end