actionpack 4.0.1 → 4.2.11.1

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 (241) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +402 -1173
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/lib/abstract_controller/base.rb +39 -7
  6. data/lib/abstract_controller/callbacks.rb +32 -53
  7. data/lib/abstract_controller/collector.rb +11 -1
  8. data/lib/abstract_controller/helpers.rb +26 -16
  9. data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
  10. data/lib/abstract_controller/rendering.rb +57 -127
  11. data/lib/abstract_controller/url_for.rb +1 -1
  12. data/lib/abstract_controller.rb +1 -2
  13. data/lib/action_controller/base.rb +19 -10
  14. data/lib/action_controller/caching/fragments.rb +7 -1
  15. data/lib/action_controller/caching.rb +2 -12
  16. data/lib/action_controller/log_subscriber.rb +29 -20
  17. data/lib/action_controller/metal/conditional_get.rb +37 -12
  18. data/lib/action_controller/metal/data_streaming.rb +1 -1
  19. data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
  20. data/lib/action_controller/metal/exceptions.rb +1 -1
  21. data/lib/action_controller/metal/flash.rb +17 -0
  22. data/lib/action_controller/metal/force_ssl.rb +2 -2
  23. data/lib/action_controller/metal/head.rb +8 -6
  24. data/lib/action_controller/metal/helpers.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +45 -23
  26. data/lib/action_controller/metal/instrumentation.rb +9 -6
  27. data/lib/action_controller/metal/live.rb +173 -20
  28. data/lib/action_controller/metal/mime_responds.rb +127 -232
  29. data/lib/action_controller/metal/params_wrapper.rb +16 -9
  30. data/lib/action_controller/metal/rack_delegation.rb +1 -1
  31. data/lib/action_controller/metal/redirecting.rb +34 -26
  32. data/lib/action_controller/metal/renderers.rb +39 -12
  33. data/lib/action_controller/metal/rendering.rb +41 -14
  34. data/lib/action_controller/metal/request_forgery_protection.rb +147 -19
  35. data/lib/action_controller/metal/streaming.rb +19 -21
  36. data/lib/action_controller/metal/strong_parameters.rb +166 -22
  37. data/lib/action_controller/metal/testing.rb +0 -1
  38. data/lib/action_controller/metal/url_for.rb +11 -12
  39. data/lib/action_controller/metal.rb +14 -8
  40. data/lib/action_controller/model_naming.rb +1 -1
  41. data/lib/action_controller/railtie.rb +5 -1
  42. data/lib/action_controller/test_case.rb +160 -94
  43. data/lib/action_controller.rb +2 -18
  44. data/lib/action_dispatch/http/cache.rb +5 -4
  45. data/lib/action_dispatch/http/filter_parameters.rb +2 -2
  46. data/lib/action_dispatch/http/filter_redirect.rb +5 -4
  47. data/lib/action_dispatch/http/headers.rb +46 -10
  48. data/lib/action_dispatch/http/mime_negotiation.rb +31 -4
  49. data/lib/action_dispatch/http/mime_type.rb +25 -26
  50. data/lib/action_dispatch/http/mime_types.rb +1 -0
  51. data/lib/action_dispatch/http/parameter_filter.rb +1 -1
  52. data/lib/action_dispatch/http/parameters.rb +25 -41
  53. data/lib/action_dispatch/http/request.rb +49 -32
  54. data/lib/action_dispatch/http/response.rb +127 -25
  55. data/lib/action_dispatch/http/upload.rb +9 -21
  56. data/lib/action_dispatch/http/url.rb +97 -70
  57. data/lib/action_dispatch/journey/formatter.rb +35 -19
  58. data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
  59. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
  60. data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -33
  61. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  62. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  63. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
  64. data/lib/action_dispatch/journey/nodes/node.rb +4 -0
  65. data/lib/action_dispatch/journey/parser.rb +51 -59
  66. data/lib/action_dispatch/journey/parser.y +12 -10
  67. data/lib/action_dispatch/journey/path/pattern.rb +16 -19
  68. data/lib/action_dispatch/journey/route.rb +8 -19
  69. data/lib/action_dispatch/journey/router/strexp.rb +9 -6
  70. data/lib/action_dispatch/journey/router/utils.rb +54 -18
  71. data/lib/action_dispatch/journey/router.rb +53 -75
  72. data/lib/action_dispatch/journey/routes.rb +4 -0
  73. data/lib/action_dispatch/journey/scanner.rb +5 -5
  74. data/lib/action_dispatch/journey/visitors.rb +81 -60
  75. data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
  76. data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
  77. data/lib/action_dispatch/middleware/callbacks.rb +7 -7
  78. data/lib/action_dispatch/middleware/cookies.rb +119 -43
  79. data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -13
  80. data/lib/action_dispatch/middleware/exception_wrapper.rb +60 -20
  81. data/lib/action_dispatch/middleware/flash.rb +37 -24
  82. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  83. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
  84. data/lib/action_dispatch/middleware/reloader.rb +11 -2
  85. data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
  86. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +8 -7
  89. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -2
  90. data/lib/action_dispatch/middleware/ssl.rb +10 -7
  91. data/lib/action_dispatch/middleware/static.rb +79 -23
  92. data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
  93. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  94. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
  95. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  96. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  97. data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +1 -1
  98. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  99. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  102. data/lib/action_dispatch/middleware/templates/rescues/{routing_error.erb → routing_error.html.erb} +3 -1
  103. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  106. data/lib/action_dispatch/middleware/templates/rescues/{unknown_action.erb → unknown_action.html.erb} +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  108. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
  109. data/lib/action_dispatch/railtie.rb +5 -2
  110. data/lib/action_dispatch/request/session.rb +12 -0
  111. data/lib/action_dispatch/request/utils.rb +35 -0
  112. data/lib/action_dispatch/routing/endpoint.rb +10 -0
  113. data/lib/action_dispatch/routing/inspector.rb +11 -17
  114. data/lib/action_dispatch/routing/mapper.rb +519 -312
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +204 -79
  116. data/lib/action_dispatch/routing/redirection.rb +51 -26
  117. data/lib/action_dispatch/routing/route_set.rb +331 -206
  118. data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
  119. data/lib/action_dispatch/routing/url_for.rb +19 -5
  120. data/lib/action_dispatch/routing.rb +9 -6
  121. data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
  122. data/lib/action_dispatch/testing/assertions/response.rb +9 -15
  123. data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
  124. data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
  125. data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
  126. data/lib/action_dispatch/testing/assertions.rb +11 -7
  127. data/lib/action_dispatch/testing/integration.rb +31 -29
  128. data/lib/action_dispatch/testing/test_request.rb +1 -1
  129. data/lib/action_dispatch/testing/test_response.rb +1 -5
  130. data/lib/action_dispatch.rb +5 -8
  131. data/lib/action_pack/gem_version.rb +15 -0
  132. data/lib/action_pack/version.rb +4 -7
  133. data/lib/action_pack.rb +1 -1
  134. metadata +77 -159
  135. data/lib/abstract_controller/layouts.rb +0 -423
  136. data/lib/abstract_controller/view_paths.rb +0 -96
  137. data/lib/action_controller/deprecated/integration_test.rb +0 -5
  138. data/lib/action_controller/deprecated.rb +0 -7
  139. data/lib/action_controller/metal/responder.rb +0 -287
  140. data/lib/action_controller/record_identifier.rb +0 -31
  141. data/lib/action_controller/vendor/html-scanner.rb +0 -5
  142. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -24
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -7
  144. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -43
  145. data/lib/action_view/base.rb +0 -201
  146. data/lib/action_view/buffers.rb +0 -49
  147. data/lib/action_view/context.rb +0 -36
  148. data/lib/action_view/dependency_tracker.rb +0 -93
  149. data/lib/action_view/digestor.rb +0 -113
  150. data/lib/action_view/flows.rb +0 -76
  151. data/lib/action_view/helpers/active_model_helper.rb +0 -49
  152. data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
  153. data/lib/action_view/helpers/asset_url_helper.rb +0 -355
  154. data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
  155. data/lib/action_view/helpers/cache_helper.rb +0 -196
  156. data/lib/action_view/helpers/capture_helper.rb +0 -216
  157. data/lib/action_view/helpers/controller_helper.rb +0 -25
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -30
  159. data/lib/action_view/helpers/date_helper.rb +0 -1083
  160. data/lib/action_view/helpers/debug_helper.rb +0 -39
  161. data/lib/action_view/helpers/form_helper.rb +0 -1880
  162. data/lib/action_view/helpers/form_options_helper.rb +0 -838
  163. data/lib/action_view/helpers/form_tag_helper.rb +0 -785
  164. data/lib/action_view/helpers/javascript_helper.rb +0 -117
  165. data/lib/action_view/helpers/number_helper.rb +0 -441
  166. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  167. data/lib/action_view/helpers/record_tag_helper.rb +0 -106
  168. data/lib/action_view/helpers/rendering_helper.rb +0 -90
  169. data/lib/action_view/helpers/sanitize_helper.rb +0 -256
  170. data/lib/action_view/helpers/tag_helper.rb +0 -173
  171. data/lib/action_view/helpers/tags/base.rb +0 -148
  172. data/lib/action_view/helpers/tags/check_box.rb +0 -64
  173. data/lib/action_view/helpers/tags/checkable.rb +0 -16
  174. data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -44
  175. data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
  176. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
  177. data/lib/action_view/helpers/tags/collection_select.rb +0 -28
  178. data/lib/action_view/helpers/tags/color_field.rb +0 -25
  179. data/lib/action_view/helpers/tags/date_field.rb +0 -13
  180. data/lib/action_view/helpers/tags/date_select.rb +0 -72
  181. data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
  182. data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
  183. data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
  184. data/lib/action_view/helpers/tags/email_field.rb +0 -8
  185. data/lib/action_view/helpers/tags/file_field.rb +0 -8
  186. data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
  187. data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
  188. data/lib/action_view/helpers/tags/label.rb +0 -66
  189. data/lib/action_view/helpers/tags/month_field.rb +0 -13
  190. data/lib/action_view/helpers/tags/number_field.rb +0 -18
  191. data/lib/action_view/helpers/tags/password_field.rb +0 -12
  192. data/lib/action_view/helpers/tags/radio_button.rb +0 -31
  193. data/lib/action_view/helpers/tags/range_field.rb +0 -8
  194. data/lib/action_view/helpers/tags/search_field.rb +0 -24
  195. data/lib/action_view/helpers/tags/select.rb +0 -40
  196. data/lib/action_view/helpers/tags/tel_field.rb +0 -8
  197. data/lib/action_view/helpers/tags/text_area.rb +0 -18
  198. data/lib/action_view/helpers/tags/text_field.rb +0 -29
  199. data/lib/action_view/helpers/tags/time_field.rb +0 -13
  200. data/lib/action_view/helpers/tags/time_select.rb +0 -8
  201. data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
  202. data/lib/action_view/helpers/tags/url_field.rb +0 -8
  203. data/lib/action_view/helpers/tags/week_field.rb +0 -13
  204. data/lib/action_view/helpers/tags.rb +0 -39
  205. data/lib/action_view/helpers/text_helper.rb +0 -443
  206. data/lib/action_view/helpers/translation_helper.rb +0 -107
  207. data/lib/action_view/helpers/url_helper.rb +0 -635
  208. data/lib/action_view/helpers.rb +0 -58
  209. data/lib/action_view/locale/en.yml +0 -56
  210. data/lib/action_view/log_subscriber.rb +0 -30
  211. data/lib/action_view/lookup_context.rb +0 -241
  212. data/lib/action_view/model_naming.rb +0 -12
  213. data/lib/action_view/path_set.rb +0 -77
  214. data/lib/action_view/railtie.rb +0 -43
  215. data/lib/action_view/record_identifier.rb +0 -84
  216. data/lib/action_view/renderer/abstract_renderer.rb +0 -47
  217. data/lib/action_view/renderer/partial_renderer.rb +0 -492
  218. data/lib/action_view/renderer/renderer.rb +0 -50
  219. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
  220. data/lib/action_view/renderer/template_renderer.rb +0 -96
  221. data/lib/action_view/routing_url_for.rb +0 -107
  222. data/lib/action_view/tasks/dependencies.rake +0 -17
  223. data/lib/action_view/template/error.rb +0 -138
  224. data/lib/action_view/template/handlers/builder.rb +0 -26
  225. data/lib/action_view/template/handlers/erb.rb +0 -146
  226. data/lib/action_view/template/handlers/raw.rb +0 -11
  227. data/lib/action_view/template/handlers.rb +0 -53
  228. data/lib/action_view/template/resolver.rb +0 -326
  229. data/lib/action_view/template/text.rb +0 -34
  230. data/lib/action_view/template/types.rb +0 -57
  231. data/lib/action_view/template.rb +0 -339
  232. data/lib/action_view/test_case.rb +0 -270
  233. data/lib/action_view/testing/resolvers.rb +0 -50
  234. data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
  235. data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
  236. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
  237. data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
  238. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
  239. data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
  240. data/lib/action_view/vendor/html-scanner.rb +0 -20
  241. data/lib/action_view.rb +0 -93
@@ -1,8 +1,11 @@
1
1
  require 'active_support/core_ext/hash/indifferent_access'
2
2
  require 'active_support/core_ext/array/wrap'
3
+ require 'active_support/core_ext/string/filters'
4
+ require 'active_support/deprecation'
3
5
  require 'active_support/rescuable'
4
6
  require 'action_dispatch/http/upload'
5
7
  require 'stringio'
8
+ require 'set'
6
9
 
7
10
  module ActionController
8
11
  # Raised when a required parameter is missing.
@@ -17,28 +20,30 @@ module ActionController
17
20
 
18
21
  def initialize(param) # :nodoc:
19
22
  @param = param
20
- super("param not found: #{param}")
23
+ super("param is missing or the value is empty: #{param}")
21
24
  end
22
25
  end
23
26
 
24
- # Raised when a supplied parameter is not expected.
27
+ # Raised when a supplied parameter is not expected and
28
+ # ActionController::Parameters.action_on_unpermitted_parameters
29
+ # is set to <tt>:raise</tt>.
25
30
  #
26
31
  # params = ActionController::Parameters.new(a: "123", b: "456")
27
32
  # params.permit(:c)
28
- # # => ActionController::UnpermittedParameters: found unexpected keys: a, b
33
+ # # => ActionController::UnpermittedParameters: found unpermitted parameters: a, b
29
34
  class UnpermittedParameters < IndexError
30
35
  attr_reader :params # :nodoc:
31
36
 
32
37
  def initialize(params) # :nodoc:
33
38
  @params = params
34
- super("found unpermitted parameters: #{params.join(", ")}")
39
+ super("found unpermitted parameter#{'s' if params.size > 1 }: #{params.join(", ")}")
35
40
  end
36
41
  end
37
42
 
38
43
  # == Action Controller \Parameters
39
44
  #
40
45
  # Allows to choose which attributes should be whitelisted for mass updating
41
- # and thus prevent accidentally exposing that which shouldnt be exposed.
46
+ # and thus prevent accidentally exposing that which shouldn't be exposed.
42
47
  # Provides two methods for this purpose: #require and #permit. The former is
43
48
  # used to mark parameters as required. The latter is used to set the parameter
44
49
  # as permitted and limit which attributes should be allowed for mass updating.
@@ -89,7 +94,11 @@ module ActionController
89
94
  # params.permit(:c)
90
95
  # # => ActionController::UnpermittedParameters: found unpermitted keys: a, b
91
96
  #
92
- # <tt>ActionController::Parameters</tt> is inherited from
97
+ # Please note that these options *are not thread-safe*. In a multi-threaded
98
+ # environment they should only be set once at boot-time and never mutated at
99
+ # runtime.
100
+ #
101
+ # <tt>ActionController::Parameters</tt> inherits from
93
102
  # <tt>ActiveSupport::HashWithIndifferentAccess</tt>, this means
94
103
  # that you can fetch values using either <tt>:key</tt> or <tt>"key"</tt>.
95
104
  #
@@ -100,9 +109,25 @@ module ActionController
100
109
  cattr_accessor :permit_all_parameters, instance_accessor: false
101
110
  cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
102
111
 
103
- # Never raise an UnpermittedParameters exception because of these params
104
- # are present. They are added by Rails and it's of no concern.
105
- NEVER_UNPERMITTED_PARAMS = %w( controller action )
112
+ # By default, never raise an UnpermittedParameters exception if these
113
+ # params are present. The default includes both 'controller' and 'action'
114
+ # because they are added by Rails and should be of no concern. One way
115
+ # to change these is to specify `always_permitted_parameters` in your
116
+ # config. For instance:
117
+ #
118
+ # config.always_permitted_parameters = %w( controller action format )
119
+ cattr_accessor :always_permitted_parameters
120
+ self.always_permitted_parameters = %w( controller action )
121
+
122
+ def self.const_missing(const_name)
123
+ super unless const_name == :NEVER_UNPERMITTED_PARAMS
124
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
125
+ `ActionController::Parameters::NEVER_UNPERMITTED_PARAMS` has been deprecated.
126
+ Use `ActionController::Parameters.always_permitted_parameters` instead.
127
+ MSG
128
+
129
+ always_permitted_parameters
130
+ end
106
131
 
107
132
  # Returns a new instance of <tt>ActionController::Parameters</tt>.
108
133
  # Also, sets the +permitted+ attribute to the default value of
@@ -125,6 +150,54 @@ module ActionController
125
150
  @permitted = self.class.permit_all_parameters
126
151
  end
127
152
 
153
+ # Returns a safe +Hash+ representation of this parameter with all
154
+ # unpermitted keys removed.
155
+ #
156
+ # params = ActionController::Parameters.new({
157
+ # name: 'Senjougahara Hitagi',
158
+ # oddity: 'Heavy stone crab'
159
+ # })
160
+ # params.to_h # => {}
161
+ #
162
+ # safe_params = params.permit(:name)
163
+ # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
164
+ def to_h
165
+ if permitted?
166
+ to_hash
167
+ else
168
+ slice(*self.class.always_permitted_parameters).permit!.to_h
169
+ end
170
+ end
171
+
172
+ # Returns an unsafe, unfiltered +Hash+ representation of this parameter.
173
+ def to_unsafe_h
174
+ to_hash
175
+ end
176
+ alias_method :to_unsafe_hash, :to_unsafe_h
177
+
178
+ # Convert all hashes in values into parameters, then yield each pair like
179
+ # the same way as <tt>Hash#each_pair</tt>
180
+ def each_pair(&block)
181
+ super do |key, value|
182
+ convert_hashes_to_parameters(key, value)
183
+ end
184
+
185
+ super
186
+ end
187
+
188
+ alias_method :each, :each_pair
189
+
190
+ # Attribute that keeps track of converted arrays, if any, to avoid double
191
+ # looping in the common use case permit + mass-assignment. Defined in a
192
+ # method to instantiate it only if needed.
193
+ #
194
+ # Testing membership still loops, but it's going to be faster than our own
195
+ # loop that converts values. Also, we are not going to build a new array
196
+ # object per fetch.
197
+ def converted_arrays
198
+ @converted_arrays ||= Set.new
199
+ end
200
+
128
201
  # Returns +true+ if the parameter is permitted, +false+ otherwise.
129
202
  #
130
203
  # params = ActionController::Parameters.new
@@ -149,8 +222,9 @@ module ActionController
149
222
  # Person.new(params) # => #<Person id: nil, name: "Francesco">
150
223
  def permit!
151
224
  each_pair do |key, value|
152
- convert_hashes_to_parameters(key, value)
153
- self[key].permit! if self[key].respond_to? :permit!
225
+ Array.wrap(value).each do |v|
226
+ v.permit! if v.respond_to? :permit!
227
+ end
154
228
  end
155
229
 
156
230
  @permitted = true
@@ -170,7 +244,12 @@ module ActionController
170
244
  # ActionController::Parameters.new(person: {}).require(:person)
171
245
  # # => ActionController::ParameterMissing: param not found: person
172
246
  def require(key)
173
- self[key].presence || raise(ParameterMissing.new(key))
247
+ value = self[key]
248
+ if value.present? || value == false
249
+ value
250
+ else
251
+ raise ParameterMissing.new(key)
252
+ end
174
253
  end
175
254
 
176
255
  # Alias of #require.
@@ -284,7 +363,7 @@ module ActionController
284
363
  # params.fetch(:none, 'Francesco') # => "Francesco"
285
364
  # params.fetch(:none) { 'Francesco' } # => "Francesco"
286
365
  def fetch(key, *args)
287
- convert_hashes_to_parameters(key, super)
366
+ convert_hashes_to_parameters(key, super, false)
288
367
  rescue KeyError
289
368
  raise ActionController::ParameterMissing.new(key)
290
369
  end
@@ -297,11 +376,56 @@ module ActionController
297
376
  # params.slice(:a, :b) # => {"a"=>1, "b"=>2}
298
377
  # params.slice(:d) # => {}
299
378
  def slice(*keys)
300
- self.class.new(super).tap do |new_instance|
301
- new_instance.instance_variable_set :@permitted, @permitted
379
+ new_instance_with_inherited_permitted_status(super)
380
+ end
381
+
382
+ # Removes and returns the key/value pairs matching the given keys.
383
+ #
384
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
385
+ # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
386
+ # params # => {"c"=>3}
387
+ def extract!(*keys)
388
+ new_instance_with_inherited_permitted_status(super)
389
+ end
390
+
391
+ # Returns a new <tt>ActionController::Parameters</tt> with the results of
392
+ # running +block+ once for every value. The keys are unchanged.
393
+ #
394
+ # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
395
+ # params.transform_values { |x| x * 2 }
396
+ # # => {"a"=>2, "b"=>4, "c"=>6}
397
+ def transform_values
398
+ if block_given?
399
+ new_instance_with_inherited_permitted_status(super)
400
+ else
401
+ super
402
+ end
403
+ end
404
+
405
+ # This method is here only to make sure that the returned object has the
406
+ # correct +permitted+ status. It should not matter since the parent of
407
+ # this object is +HashWithIndifferentAccess+
408
+ def transform_keys # :nodoc:
409
+ if block_given?
410
+ new_instance_with_inherited_permitted_status(super)
411
+ else
412
+ super
302
413
  end
303
414
  end
304
415
 
416
+ # Deletes and returns a key-value pair from +Parameters+ whose key is equal
417
+ # to key. If the key is not found, returns the default value. If the
418
+ # optional code block is given and the key is not found, pass in the key
419
+ # and return the result of block.
420
+ def delete(key, &block)
421
+ convert_hashes_to_parameters(key, super, false)
422
+ end
423
+
424
+ # Equivalent to Hash#keep_if, but returns nil if no changes were made.
425
+ def select!(&block)
426
+ convert_value_to_parameters(super)
427
+ end
428
+
305
429
  # Returns an exact copy of the <tt>ActionController::Parameters</tt>
306
430
  # instance. +permitted+ state is kept on the duped object.
307
431
  #
@@ -312,17 +436,37 @@ module ActionController
312
436
  # copy_params.permitted? # => true
313
437
  def dup
314
438
  super.tap do |duplicate|
315
- duplicate.instance_variable_set :@permitted, @permitted
439
+ duplicate.permitted = @permitted
316
440
  end
317
441
  end
318
442
 
443
+ protected
444
+ def permitted=(new_permitted)
445
+ @permitted = new_permitted
446
+ end
447
+
319
448
  private
320
- def convert_hashes_to_parameters(key, value)
321
- if value.is_a?(Parameters) || !value.is_a?(Hash)
449
+ def new_instance_with_inherited_permitted_status(hash)
450
+ self.class.new(hash).tap do |new_instance|
451
+ new_instance.permitted = @permitted
452
+ end
453
+ end
454
+
455
+ def convert_hashes_to_parameters(key, value, assign_if_converted=true)
456
+ converted = convert_value_to_parameters(value)
457
+ self[key] = converted if assign_if_converted && !converted.equal?(value)
458
+ converted
459
+ end
460
+
461
+ def convert_value_to_parameters(value)
462
+ if value.is_a?(Array) && !converted_arrays.member?(value)
463
+ converted = value.map { |_| convert_value_to_parameters(_) }
464
+ converted_arrays << converted
465
+ converted
466
+ elsif value.is_a?(Parameters) || !value.is_a?(Hash)
322
467
  value
323
468
  else
324
- # Convert to Parameters on first access
325
- self[key] = self.class.new(value)
469
+ self.class.new(value)
326
470
  end
327
471
  end
328
472
 
@@ -356,7 +500,7 @@ module ActionController
356
500
  end
357
501
 
358
502
  def unpermitted_keys(params)
359
- self.keys - params.keys - NEVER_UNPERMITTED_PARAMS
503
+ self.keys - params.keys - self.always_permitted_parameters
360
504
  end
361
505
 
362
506
  #
@@ -478,7 +622,7 @@ module ActionController
478
622
  # end
479
623
  # end
480
624
  #
481
- # In order to use <tt>accepts_nested_attribute_for</tt> with Strong \Parameters, you
625
+ # In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you
482
626
  # will need to specify which nested attributes should be whitelisted.
483
627
  #
484
628
  # class Person
@@ -17,7 +17,6 @@ module ActionController
17
17
 
18
18
  def recycle!
19
19
  @_url_options = nil
20
- self.response_body = nil
21
20
  self.formats = nil
22
21
  self.params = nil
23
22
  end
@@ -23,25 +23,24 @@ module ActionController
23
23
  include AbstractController::UrlFor
24
24
 
25
25
  def url_options
26
- @_url_options ||= super.reverse_merge(
26
+ @_url_options ||= {
27
27
  :host => request.host,
28
28
  :port => request.optional_port,
29
29
  :protocol => request.protocol,
30
- :_recall => request.symbolized_path_parameters
31
- ).freeze
30
+ :_recall => request.path_parameters
31
+ }.merge!(super).freeze
32
32
 
33
- if (same_origin = _routes.equal?(env["action_dispatch.routes"])) ||
33
+ if (same_origin = _routes.equal?(env["action_dispatch.routes".freeze])) ||
34
34
  (script_name = env["ROUTES_#{_routes.object_id}_SCRIPT_NAME"]) ||
35
- (original_script_name = env['ORIGINAL_SCRIPT_NAME'])
35
+ (original_script_name = env['ORIGINAL_SCRIPT_NAME'.freeze])
36
36
 
37
- @_url_options.dup.tap do |options|
38
- if original_script_name
39
- options[:original_script_name] = original_script_name
40
- else
41
- options[:script_name] = same_origin ? request.script_name.dup : script_name
42
- end
43
- options.freeze
37
+ options = @_url_options.dup
38
+ if original_script_name
39
+ options[:original_script_name] = original_script_name
40
+ else
41
+ options[:script_name] = same_origin ? request.script_name.dup : script_name
44
42
  end
43
+ options.freeze
45
44
  else
46
45
  @_url_options
47
46
  end
@@ -30,10 +30,8 @@ module ActionController
30
30
  end
31
31
  end
32
32
 
33
- def build(action, app=nil, &block)
34
- app ||= block
33
+ def build(action, app = Proc.new)
35
34
  action = action.to_s
36
- raise "MiddlewareStack#build requires an app" unless app
37
35
 
38
36
  middlewares.reverse.inject(app) do |a, middleware|
39
37
  middleware.valid?(action) ? middleware.build(a) : a
@@ -70,7 +68,8 @@ module ActionController
70
68
  # can do the following:
71
69
  #
72
70
  # class HelloController < ActionController::Metal
73
- # include ActionController::Rendering
71
+ # include AbstractController::Rendering
72
+ # include ActionView::Layouts
74
73
  # append_view_path "#{Rails.root}/app/views"
75
74
  #
76
75
  # def index
@@ -166,7 +165,7 @@ module ActionController
166
165
  headers["Location"] = url
167
166
  end
168
167
 
169
- # basic url_for that can be overridden for more robust functionality
168
+ # Basic url_for that can be overridden for more robust functionality
170
169
  def url_for(string)
171
170
  string
172
171
  end
@@ -174,6 +173,7 @@ module ActionController
174
173
  def status
175
174
  @_status
176
175
  end
176
+ alias :response_code :status # :nodoc:
177
177
 
178
178
  def status=(status)
179
179
  @_status = Rack::Utils.status_code(status)
@@ -184,6 +184,7 @@ module ActionController
184
184
  super
185
185
  end
186
186
 
187
+ # Tests if render or redirect has already happened.
187
188
  def performed?
188
189
  response_body || (response && response.committed?)
189
190
  end
@@ -222,13 +223,18 @@ module ActionController
222
223
  # Makes the controller a Rack endpoint that runs the action in the given
223
224
  # +env+'s +action_dispatch.request.path_parameters+ key.
224
225
  def self.call(env)
225
- action(env['action_dispatch.request.path_parameters'][:action]).call(env)
226
+ req = ActionDispatch::Request.new env
227
+ action(req.path_parameters[:action]).call(env)
226
228
  end
227
229
 
228
230
  # Returns a Rack endpoint for the given action name.
229
231
  def self.action(name, klass = ActionDispatch::Request)
230
- middleware_stack.build(name.to_s) do |env|
231
- new.dispatch(name, klass.new(env))
232
+ if middleware_stack.any?
233
+ middleware_stack.build(name) do |env|
234
+ new.dispatch(name, klass.new(env))
235
+ end
236
+ else
237
+ lambda { |env| new.dispatch(name, klass.new(env)) }
232
238
  end
233
239
  end
234
240
  end
@@ -6,7 +6,7 @@ module ActionController
6
6
  end
7
7
 
8
8
  def model_name_from_record_or_class(record_or_class)
9
- (record_or_class.is_a?(Class) ? record_or_class : convert_to_model(record_or_class).class).model_name
9
+ convert_to_model(record_or_class).model_name
10
10
  end
11
11
  end
12
12
  end
@@ -1,9 +1,9 @@
1
1
  require "rails"
2
2
  require "action_controller"
3
3
  require "action_dispatch/railtie"
4
- require "action_view/railtie"
5
4
  require "abstract_controller/railties/routes_helpers"
6
5
  require "action_controller/railties/helpers"
6
+ require "action_view/railtie"
7
7
 
8
8
  module ActionController
9
9
  class Railtie < Rails::Railtie #:nodoc:
@@ -23,6 +23,10 @@ module ActionController
23
23
  options = app.config.action_controller
24
24
 
25
25
  ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
26
+ if app.config.action_controller[:always_permitted_parameters]
27
+ ActionController::Parameters.always_permitted_parameters =
28
+ app.config.action_controller.delete(:always_permitted_parameters)
29
+ end
26
30
  ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
27
31
  (Rails.env.test? || Rails.env.development?) ? :log : false
28
32
  end