actionpack 4.1.16 → 4.2.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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +163 -690
  3. data/README.rdoc +7 -2
  4. data/lib/abstract_controller/base.rb +16 -6
  5. data/lib/abstract_controller/callbacks.rb +28 -51
  6. data/lib/abstract_controller/helpers.rb +0 -3
  7. data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
  8. data/lib/abstract_controller/rendering.rb +1 -7
  9. data/lib/abstract_controller/url_for.rb +1 -1
  10. data/lib/action_controller.rb +1 -0
  11. data/lib/action_controller/base.rb +2 -1
  12. data/lib/action_controller/caching.rb +1 -1
  13. data/lib/action_controller/caching/fragments.rb +7 -1
  14. data/lib/action_controller/log_subscriber.rb +26 -25
  15. data/lib/action_controller/metal.rb +11 -7
  16. data/lib/action_controller/metal/conditional_get.rb +31 -6
  17. data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
  18. data/lib/action_controller/metal/force_ssl.rb +1 -1
  19. data/lib/action_controller/metal/head.rb +2 -0
  20. data/lib/action_controller/metal/http_authentication.rb +3 -15
  21. data/lib/action_controller/metal/instrumentation.rb +4 -7
  22. data/lib/action_controller/metal/live.rb +57 -6
  23. data/lib/action_controller/metal/mime_responds.rb +17 -227
  24. data/lib/action_controller/metal/redirecting.rb +14 -8
  25. data/lib/action_controller/metal/renderers.rb +19 -3
  26. data/lib/action_controller/metal/rendering.rb +2 -6
  27. data/lib/action_controller/metal/request_forgery_protection.rb +75 -7
  28. data/lib/action_controller/metal/streaming.rb +1 -1
  29. data/lib/action_controller/metal/strong_parameters.rb +111 -11
  30. data/lib/action_controller/metal/url_for.rb +11 -12
  31. data/lib/action_controller/model_naming.rb +1 -1
  32. data/lib/action_controller/railtie.rb +4 -0
  33. data/lib/action_controller/test_case.rb +87 -75
  34. data/lib/action_dispatch/http/cache.rb +1 -1
  35. data/lib/action_dispatch/http/filter_parameters.rb +2 -2
  36. data/lib/action_dispatch/http/headers.rb +43 -9
  37. data/lib/action_dispatch/http/mime_negotiation.rb +10 -4
  38. data/lib/action_dispatch/http/mime_type.rb +2 -16
  39. data/lib/action_dispatch/http/parameter_filter.rb +1 -1
  40. data/lib/action_dispatch/http/parameters.rb +11 -26
  41. data/lib/action_dispatch/http/request.rb +30 -10
  42. data/lib/action_dispatch/http/response.rb +52 -17
  43. data/lib/action_dispatch/http/upload.rb +3 -8
  44. data/lib/action_dispatch/http/url.rb +87 -70
  45. data/lib/action_dispatch/journey/formatter.rb +18 -17
  46. data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
  47. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
  48. data/lib/action_dispatch/journey/gtg/transition_table.rb +18 -26
  49. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  50. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  51. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
  52. data/lib/action_dispatch/journey/nodes/node.rb +4 -0
  53. data/lib/action_dispatch/journey/parser.rb +52 -60
  54. data/lib/action_dispatch/journey/parser.y +11 -10
  55. data/lib/action_dispatch/journey/path/pattern.rb +16 -19
  56. data/lib/action_dispatch/journey/route.rb +3 -18
  57. data/lib/action_dispatch/journey/router.rb +34 -65
  58. data/lib/action_dispatch/journey/router/strexp.rb +9 -6
  59. data/lib/action_dispatch/journey/routes.rb +0 -4
  60. data/lib/action_dispatch/journey/visitors.rb +81 -92
  61. data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
  62. data/lib/action_dispatch/middleware/cookies.rb +27 -31
  63. data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -3
  64. data/lib/action_dispatch/middleware/exception_wrapper.rb +19 -17
  65. data/lib/action_dispatch/middleware/flash.rb +7 -4
  66. data/lib/action_dispatch/middleware/public_exceptions.rb +13 -8
  67. data/lib/action_dispatch/middleware/remote_ip.rb +3 -3
  68. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  69. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
  70. data/lib/action_dispatch/middleware/show_exceptions.rb +1 -0
  71. data/lib/action_dispatch/middleware/static.rb +22 -23
  72. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +22 -18
  73. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +36 -8
  74. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +2 -8
  75. data/lib/action_dispatch/middleware/templates/rescues/{diagnostics.erb → diagnostics.html.erb} +0 -0
  76. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  77. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
  78. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -24
  79. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +0 -1
  80. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +119 -63
  81. data/lib/action_dispatch/routing/endpoint.rb +10 -0
  82. data/lib/action_dispatch/routing/inspector.rb +4 -11
  83. data/lib/action_dispatch/routing/mapper.rb +399 -278
  84. data/lib/action_dispatch/routing/polymorphic_routes.rb +190 -78
  85. data/lib/action_dispatch/routing/redirection.rb +10 -12
  86. data/lib/action_dispatch/routing/route_set.rb +224 -177
  87. data/lib/action_dispatch/routing/url_for.rb +9 -4
  88. data/lib/action_dispatch/testing/assertions.rb +11 -7
  89. data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
  90. data/lib/action_dispatch/testing/assertions/response.rb +2 -7
  91. data/lib/action_dispatch/testing/assertions/routing.rb +9 -9
  92. data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
  93. data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
  94. data/lib/action_dispatch/testing/integration.rb +15 -18
  95. data/lib/action_dispatch/testing/test_request.rb +1 -1
  96. data/lib/action_dispatch/testing/test_response.rb +5 -1
  97. data/lib/action_pack/gem_version.rb +3 -3
  98. metadata +57 -15
  99. data/lib/action_controller/metal/responder.rb +0 -297
@@ -32,7 +32,7 @@ The latest version of Action Pack can be installed with RubyGems:
32
32
 
33
33
  Source code can be downloaded as part of the Rails project on GitHub
34
34
 
35
- * https://github.com/rails/rails/tree/4-1-stable/actionpack
35
+ * https://github.com/rails/rails/tree/master/actionpack
36
36
 
37
37
 
38
38
  == License
@@ -48,6 +48,11 @@ API documentation is at
48
48
 
49
49
  * http://api.rubyonrails.org
50
50
 
51
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
51
+ Bug reports can be filed for the Ruby on Rails project here:
52
52
 
53
53
  * https://github.com/rails/rails/issues
54
+
55
+ Feature requests should be discussed on the rails-core mailing list here:
56
+
57
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
58
+
@@ -8,7 +8,8 @@ module AbstractController
8
8
  class Error < StandardError #:nodoc:
9
9
  end
10
10
 
11
- class ActionNotFound < StandardError #:nodoc:
11
+ # Raised when a non-existing controller action is triggered.
12
+ class ActionNotFound < StandardError
12
13
  end
13
14
 
14
15
  # <tt>AbstractController::Base</tt> is a low-level API. Nobody should be
@@ -120,14 +121,14 @@ module AbstractController
120
121
  #
121
122
  # The actual method that is called is determined by calling
122
123
  # #method_for_action. If no method can handle the action, then an
123
- # ActionNotFound error is raised.
124
+ # AbstractController::ActionNotFound error is raised.
124
125
  #
125
126
  # ==== Returns
126
127
  # * <tt>self</tt>
127
128
  def process(action, *args)
128
- @_action_name = action_name = action.to_s
129
+ @_action_name = action.to_s
129
130
 
130
- unless action_name = _find_action_name(action_name)
131
+ unless action_name = _find_action_name(@_action_name)
131
132
  raise ActionNotFound, "The action '#{action}' could not be found for #{self.class.name}"
132
133
  end
133
134
 
@@ -163,6 +164,14 @@ module AbstractController
163
164
  _find_action_name(action_name).present?
164
165
  end
165
166
 
167
+ # Returns true if the given controller is capable of rendering
168
+ # a path. A subclass of +AbstractController::Base+
169
+ # may return false. An Email controller for example does not
170
+ # support paths, only full URLs.
171
+ def self.supports_path?
172
+ true
173
+ end
174
+
166
175
  private
167
176
 
168
177
  # Returns true if the name can be considered an action because
@@ -215,7 +224,8 @@ module AbstractController
215
224
  #
216
225
  # ==== Returns
217
226
  # * <tt>string</tt> - The name of the method that handles the action
218
- # * false - No valid method name could be found. Raise ActionNotFound.
227
+ # * false - No valid method name could be found.
228
+ # Raise AbstractController::ActionNotFound.
219
229
  def _find_action_name(action_name)
220
230
  _valid_action_name?(action_name) && method_for_action(action_name)
221
231
  end
@@ -235,7 +245,7 @@ module AbstractController
235
245
  # the case.
236
246
  #
237
247
  # If none of these conditions are true, and method_for_action
238
- # returns nil, an ActionNotFound exception will be raised.
248
+ # returns nil, an AbstractController::ActionNotFound exception will be raised.
239
249
  #
240
250
  # ==== Parameters
241
251
  # * <tt>action_name</tt> - An action name to find a method name for
@@ -42,20 +42,18 @@ module AbstractController
42
42
  end
43
43
  end
44
44
 
45
- # Skip before, after, and around action callbacks matching any of the names
46
- # Aliased as skip_filter.
45
+ # Skip before, after, and around action callbacks matching any of the names.
47
46
  #
48
47
  # ==== Parameters
49
48
  # * <tt>names</tt> - A list of valid names that could be used for
50
49
  # callbacks. Note that skipping uses Ruby equality, so it's
51
50
  # impossible to skip a callback defined using an anonymous proc
52
- # using #skip_filter
51
+ # using #skip_action_callback
53
52
  def skip_action_callback(*names)
54
53
  skip_before_action(*names)
55
54
  skip_after_action(*names)
56
55
  skip_around_action(*names)
57
56
  end
58
-
59
57
  alias_method :skip_filter, :skip_action_callback
60
58
 
61
59
  # Take callback names and an optional callback proc, normalize them,
@@ -85,7 +83,6 @@ module AbstractController
85
83
  # :call-seq: before_action(names, block)
86
84
  #
87
85
  # Append a callback before actions. See _insert_callbacks for parameter details.
88
- # Aliased as before_filter.
89
86
 
90
87
  ##
91
88
  # :method: prepend_before_action
@@ -93,7 +90,6 @@ module AbstractController
93
90
  # :call-seq: prepend_before_action(names, block)
94
91
  #
95
92
  # Prepend a callback before actions. See _insert_callbacks for parameter details.
96
- # Aliased as prepend_before_filter.
97
93
 
98
94
  ##
99
95
  # :method: skip_before_action
@@ -101,7 +97,6 @@ module AbstractController
101
97
  # :call-seq: skip_before_action(names)
102
98
  #
103
99
  # Skip a callback before actions. See _insert_callbacks for parameter details.
104
- # Aliased as skip_before_filter.
105
100
 
106
101
  ##
107
102
  # :method: append_before_action
@@ -109,7 +104,6 @@ module AbstractController
109
104
  # :call-seq: append_before_action(names, block)
110
105
  #
111
106
  # Append a callback before actions. See _insert_callbacks for parameter details.
112
- # Aliased as append_before_filter.
113
107
 
114
108
  ##
115
109
  # :method: after_action
@@ -117,7 +111,6 @@ module AbstractController
117
111
  # :call-seq: after_action(names, block)
118
112
  #
119
113
  # Append a callback after actions. See _insert_callbacks for parameter details.
120
- # Aliased as after_filter.
121
114
 
122
115
  ##
123
116
  # :method: prepend_after_action
@@ -125,7 +118,6 @@ module AbstractController
125
118
  # :call-seq: prepend_after_action(names, block)
126
119
  #
127
120
  # Prepend a callback after actions. See _insert_callbacks for parameter details.
128
- # Aliased as prepend_after_filter.
129
121
 
130
122
  ##
131
123
  # :method: skip_after_action
@@ -133,7 +125,6 @@ module AbstractController
133
125
  # :call-seq: skip_after_action(names)
134
126
  #
135
127
  # Skip a callback after actions. See _insert_callbacks for parameter details.
136
- # Aliased as skip_after_filter.
137
128
 
138
129
  ##
139
130
  # :method: append_after_action
@@ -141,7 +132,6 @@ module AbstractController
141
132
  # :call-seq: append_after_action(names, block)
142
133
  #
143
134
  # Append a callback after actions. See _insert_callbacks for parameter details.
144
- # Aliased as append_after_filter.
145
135
 
146
136
  ##
147
137
  # :method: around_action
@@ -149,7 +139,6 @@ module AbstractController
149
139
  # :call-seq: around_action(names, block)
150
140
  #
151
141
  # Append a callback around actions. See _insert_callbacks for parameter details.
152
- # Aliased as around_filter.
153
142
 
154
143
  ##
155
144
  # :method: prepend_around_action
@@ -157,7 +146,6 @@ module AbstractController
157
146
  # :call-seq: prepend_around_action(names, block)
158
147
  #
159
148
  # Prepend a callback around actions. See _insert_callbacks for parameter details.
160
- # Aliased as prepend_around_filter.
161
149
 
162
150
  ##
163
151
  # :method: skip_around_action
@@ -165,7 +153,6 @@ module AbstractController
165
153
  # :call-seq: skip_around_action(names)
166
154
  #
167
155
  # Skip a callback around actions. See _insert_callbacks for parameter details.
168
- # Aliased as skip_around_filter.
169
156
 
170
157
  ##
171
158
  # :method: append_around_action
@@ -173,46 +160,36 @@ module AbstractController
173
160
  # :call-seq: append_around_action(names, block)
174
161
  #
175
162
  # Append a callback around actions. See _insert_callbacks for parameter details.
176
- # Aliased as append_around_filter.
177
163
 
178
164
  # set up before_action, prepend_before_action, skip_before_action, etc.
179
165
  # for each of before, after, and around.
180
166
  [:before, :after, :around].each do |callback|
181
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
182
- # Append a before, after or around callback. See _insert_callbacks
183
- # for details on the allowed parameters.
184
- def #{callback}_action(*names, &blk) # def before_action(*names, &blk)
185
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
186
- set_callback(:process_action, :#{callback}, name, options) # set_callback(:process_action, :before, name, options)
187
- end # end
188
- end # end
189
-
190
- alias_method :#{callback}_filter, :#{callback}_action
191
-
192
- # Prepend a before, after or around callback. See _insert_callbacks
193
- # for details on the allowed parameters.
194
- def prepend_#{callback}_action(*names, &blk) # def prepend_before_action(*names, &blk)
195
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
196
- set_callback(:process_action, :#{callback}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
197
- end # end
198
- end # end
199
-
200
- alias_method :prepend_#{callback}_filter, :prepend_#{callback}_action
201
-
202
- # Skip a before, after or around callback. See _insert_callbacks
203
- # for details on the allowed parameters.
204
- def skip_#{callback}_action(*names) # def skip_before_action(*names)
205
- _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options|
206
- skip_callback(:process_action, :#{callback}, name, options) # skip_callback(:process_action, :before, name, options)
207
- end # end
208
- end # end
209
-
210
- alias_method :skip_#{callback}_filter, :skip_#{callback}_action
211
-
212
- # *_action is the same as append_*_action
213
- alias_method :append_#{callback}_action, :#{callback}_action # alias_method :append_before_action, :before_action
214
- alias_method :append_#{callback}_filter, :#{callback}_action # alias_method :append_before_filter, :before_action
215
- RUBY_EVAL
167
+ define_method "#{callback}_action" do |*names, &blk|
168
+ _insert_callbacks(names, blk) do |name, options|
169
+ set_callback(:process_action, callback, name, options)
170
+ end
171
+ end
172
+ alias_method :"#{callback}_filter", :"#{callback}_action"
173
+
174
+ define_method "prepend_#{callback}_action" do |*names, &blk|
175
+ _insert_callbacks(names, blk) do |name, options|
176
+ set_callback(:process_action, callback, name, options.merge(:prepend => true))
177
+ end
178
+ end
179
+ alias_method :"prepend_#{callback}_filter", :"prepend_#{callback}_action"
180
+
181
+ # Skip a before, after or around callback. See _insert_callbacks
182
+ # for details on the allowed parameters.
183
+ define_method "skip_#{callback}_action" do |*names|
184
+ _insert_callbacks(names) do |name, options|
185
+ skip_callback(:process_action, callback, name, options)
186
+ end
187
+ end
188
+ alias_method :"skip_#{callback}_filter", :"skip_#{callback}_action"
189
+
190
+ # *_action is the same as append_*_action
191
+ alias_method :"append_#{callback}_action", :"#{callback}_action"
192
+ alias_method :"append_#{callback}_filter", :"#{callback}_action"
216
193
  end
217
194
  end
218
195
  end
@@ -27,9 +27,6 @@ module AbstractController
27
27
  end
28
28
 
29
29
  module ClassMethods
30
- MissingHelperError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('AbstractController::Helpers::ClassMethods::MissingHelperError',
31
- 'AbstractController::Helpers::MissingHelperError')
32
-
33
30
  # When a class is inherited, wrap its helper module in a new module.
34
31
  # This ensures that the parent class's module can be changed
35
32
  # independently of the child class's.
@@ -1,14 +1,14 @@
1
1
  module AbstractController
2
2
  module Railties
3
3
  module RoutesHelpers
4
- def self.with(routes)
4
+ def self.with(routes, include_path_helpers = true)
5
5
  Module.new do
6
6
  define_method(:inherited) do |klass|
7
7
  super(klass)
8
8
  if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
9
- klass.send(:include, namespace.railtie_routes_url_helpers)
9
+ klass.send(:include, namespace.railtie_routes_url_helpers(include_path_helpers))
10
10
  else
11
- klass.send(:include, routes.url_helpers)
11
+ klass.send(:include, routes.url_helpers(include_path_helpers))
12
12
  end
13
13
  end
14
14
  end
@@ -77,13 +77,7 @@ module AbstractController
77
77
  # render "foo/bar" to render :file => "foo/bar".
78
78
  # :api: plugin
79
79
  def _normalize_args(action=nil, options={})
80
- if action.respond_to?(:permitted?)
81
- if action.permitted?
82
- action
83
- else
84
- raise ArgumentError, "render parameters are not permitted"
85
- end
86
- elsif action.is_a?(Hash)
80
+ if action.is_a? Hash
87
81
  action
88
82
  else
89
83
  options
@@ -11,7 +11,7 @@ module AbstractController
11
11
 
12
12
  def _routes
13
13
  raise "In order to use #url_for, you must include routing helpers explicitly. " \
14
- "For instance, `include Rails.application.routes.url_helpers"
14
+ "For instance, `include Rails.application.routes.url_helpers`."
15
15
  end
16
16
 
17
17
  module ClassMethods
@@ -17,6 +17,7 @@ module ActionController
17
17
  autoload :ConditionalGet
18
18
  autoload :Cookies
19
19
  autoload :DataStreaming
20
+ autoload :EtagWithTemplateDigest
20
21
  autoload :Flash
21
22
  autoload :ForceSSL
22
23
  autoload :Head
@@ -44,7 +44,7 @@ module ActionController
44
44
  # The full request object is available via the request accessor and is primarily used to query for HTTP headers:
45
45
  #
46
46
  # def server_ip
47
- # location = request.env["REMOTE_ADDR"]
47
+ # location = request.env["SERVER_ADDR"]
48
48
  # render plain: "This server hosted at #{location}"
49
49
  # end
50
50
  #
@@ -213,6 +213,7 @@ module ActionController
213
213
  Rendering,
214
214
  Renderers::All,
215
215
  ConditionalGet,
216
+ EtagWithTemplateDigest,
216
217
  RackDelegation,
217
218
  Caching,
218
219
  MimeResponds,
@@ -16,7 +16,7 @@ module ActionController
16
16
  # All the caching stores from ActiveSupport::Cache are available to be used as backends
17
17
  # for Action Controller caching.
18
18
  #
19
- # Configuration examples (MemoryStore is the default):
19
+ # Configuration examples (FileStore is the default):
20
20
  #
21
21
  # config.action_controller.cache_store = :memory_store
22
22
  # config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
@@ -90,7 +90,13 @@ module ActionController
90
90
  end
91
91
 
92
92
  def instrument_fragment_cache(name, key) # :nodoc:
93
- ActiveSupport::Notifications.instrument("#{name}.action_controller", :key => key){ yield }
93
+ payload = {
94
+ controller: controller_name,
95
+ action: action_name,
96
+ key: key
97
+ }
98
+
99
+ ActiveSupport::Notifications.instrument("#{name}.action_controller", payload) { yield }
94
100
  end
95
101
  end
96
102
  end
@@ -16,50 +16,51 @@ module ActionController
16
16
  end
17
17
 
18
18
  def process_action(event)
19
- return unless logger.info?
20
-
21
- payload = event.payload
22
- additions = ActionController::Base.log_process_action(payload)
23
-
24
- status = payload[:status]
25
- if status.nil? && payload[:exception].present?
26
- exception_class_name = payload[:exception].first
27
- status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
19
+ info do
20
+ payload = event.payload
21
+ additions = ActionController::Base.log_process_action(payload)
22
+
23
+ status = payload[:status]
24
+ if status.nil? && payload[:exception].present?
25
+ exception_class_name = payload[:exception].first
26
+ status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
27
+ end
28
+ message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
29
+ message << " (#{additions.join(" | ")})" unless additions.blank?
30
+ message
28
31
  end
29
- message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
30
- message << " (#{additions.join(" | ")})" unless additions.blank?
31
-
32
- info(message)
33
32
  end
34
33
 
35
34
  def halted_callback(event)
36
- info("Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected")
35
+ info { "Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected" }
37
36
  end
38
37
 
39
38
  def send_file(event)
40
- info("Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)")
39
+ info { "Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)" }
41
40
  end
42
41
 
43
42
  def redirect_to(event)
44
- info("Redirected to #{event.payload[:location]}")
43
+ info { "Redirected to #{event.payload[:location]}" }
45
44
  end
46
45
 
47
46
  def send_data(event)
48
- info("Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)")
47
+ info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
49
48
  end
50
49
 
51
50
  def unpermitted_parameters(event)
52
- unpermitted_keys = event.payload[:keys]
53
- debug("Unpermitted parameters: #{unpermitted_keys.join(", ")}")
51
+ debug do
52
+ unpermitted_keys = event.payload[:keys]
53
+ "Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{unpermitted_keys.join(", ")}"
54
+ end
54
55
  end
55
56
 
56
57
  def deep_munge(event)
57
- message = "Value for params[:#{event.payload[:keys].join('][:')}] was set "\
58
- "to nil, because it was one of [], [null] or [null, null, ...]. "\
59
- "Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation "\
60
- "for more information."\
61
-
62
- debug(message)
58
+ debug do
59
+ "Value for params[:#{event.payload[:keys].join('][:')}] was set "\
60
+ "to nil, because it was one of [], [null] or [null, null, ...]. "\
61
+ "Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation "\
62
+ "for more information."\
63
+ end
63
64
  end
64
65
 
65
66
  %w(write_fragment read_fragment exist_fragment?
@@ -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
@@ -184,7 +182,8 @@ module ActionController
184
182
  body = [body] unless body.nil? || body.respond_to?(:each)
185
183
  super
186
184
  end
187
-
185
+
186
+ # Tests if render or redirect has already happened.
188
187
  def performed?
189
188
  response_body || (response && response.committed?)
190
189
  end
@@ -223,13 +222,18 @@ module ActionController
223
222
  # Makes the controller a Rack endpoint that runs the action in the given
224
223
  # +env+'s +action_dispatch.request.path_parameters+ key.
225
224
  def self.call(env)
226
- action(env['action_dispatch.request.path_parameters'][:action]).call(env)
225
+ req = ActionDispatch::Request.new env
226
+ action(req.path_parameters[:action]).call(env)
227
227
  end
228
228
 
229
229
  # Returns a Rack endpoint for the given action name.
230
230
  def self.action(name, klass = ActionDispatch::Request)
231
- middleware_stack.build(name.to_s) do |env|
232
- new.dispatch(name, klass.new(env))
231
+ if middleware_stack.any?
232
+ middleware_stack.build(name) do |env|
233
+ new.dispatch(name, klass.new(env))
234
+ end
235
+ else
236
+ lambda { |env| new.dispatch(name, klass.new(env)) }
233
237
  end
234
238
  end
235
239