actionpack 5.0.0.beta3 → 5.0.0.beta4

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -16
  3. data/lib/abstract_controller/base.rb +2 -4
  4. data/lib/abstract_controller/error.rb +4 -0
  5. data/lib/abstract_controller/helpers.rb +2 -1
  6. data/lib/abstract_controller/rendering.rb +1 -0
  7. data/lib/action_controller/api.rb +20 -19
  8. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  9. data/lib/action_controller/metal/conditional_get.rb +52 -21
  10. data/lib/action_controller/metal/cookies.rb +1 -1
  11. data/lib/action_controller/metal/data_streaming.rb +9 -10
  12. data/lib/action_controller/metal/force_ssl.rb +4 -4
  13. data/lib/action_controller/metal/http_authentication.rb +8 -3
  14. data/lib/action_controller/metal/implicit_render.rb +55 -17
  15. data/lib/action_controller/metal/instrumentation.rb +3 -2
  16. data/lib/action_controller/metal/live.rb +2 -2
  17. data/lib/action_controller/metal/mime_responds.rb +1 -1
  18. data/lib/action_controller/metal/redirecting.rb +1 -1
  19. data/lib/action_controller/metal/request_forgery_protection.rb +3 -2
  20. data/lib/action_controller/metal/rescue.rb +6 -2
  21. data/lib/action_controller/metal/strong_parameters.rb +30 -3
  22. data/lib/action_controller/renderer.rb +1 -1
  23. data/lib/action_controller/test_case.rb +2 -2
  24. data/lib/action_dispatch.rb +1 -1
  25. data/lib/action_dispatch/http/cache.rb +49 -15
  26. data/lib/action_dispatch/http/filter_parameters.rb +9 -3
  27. data/lib/action_dispatch/http/headers.rb +2 -2
  28. data/lib/action_dispatch/http/mime_types.rb +1 -1
  29. data/lib/action_dispatch/http/request.rb +0 -1
  30. data/lib/action_dispatch/journey/formatter.rb +7 -2
  31. data/lib/action_dispatch/journey/route.rb +1 -1
  32. data/lib/action_dispatch/middleware/callbacks.rb +10 -1
  33. data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -1
  34. data/lib/action_dispatch/middleware/executor.rb +19 -0
  35. data/lib/action_dispatch/middleware/flash.rb +5 -0
  36. data/lib/action_dispatch/middleware/params_parser.rb +1 -0
  37. data/lib/action_dispatch/middleware/reloader.rb +12 -54
  38. data/lib/action_dispatch/middleware/ssl.rb +19 -3
  39. data/lib/action_dispatch/railtie.rb +2 -0
  40. data/lib/action_dispatch/request/session.rb +16 -10
  41. data/lib/action_dispatch/routing.rb +12 -3
  42. data/lib/action_dispatch/routing/inspector.rb +3 -3
  43. data/lib/action_dispatch/routing/mapper.rb +6 -3
  44. data/lib/action_dispatch/routing/route_set.rb +16 -15
  45. data/lib/action_dispatch/routing/url_for.rb +1 -1
  46. data/lib/action_dispatch/testing/assertions/routing.rb +1 -1
  47. data/lib/action_dispatch/testing/integration.rb +43 -27
  48. data/lib/action_pack/gem_version.rb +1 -1
  49. metadata +12 -11
  50. data/lib/action_dispatch/middleware/load_interlock.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c2847271b11f9c0787c4d0468c83fac6b307cbce
4
- data.tar.gz: b8df093bb286c2d9160a70cfd9d22a8343affcad
3
+ metadata.gz: 9f74fd0c4a1304d3b6de560815456c08e23b5e05
4
+ data.tar.gz: 58e4de5b07483d0062d052c853e8e2aa348134de
5
5
  SHA512:
6
- metadata.gz: 9d456ad1bbbd96908af0c0febd7922af482d88e315b83e3debba4aafe603fa3d531481c63b4e88a973b7a1910d93462e181a1cb780715aadc6d7e2677594a411
7
- data.tar.gz: 27395600e033a142f00a7550bd97d96003af16a9c81e5c1e128759e50cc5c6ca21be046f5fa7e6c77234778eb670e810c3ee9d40c7d2d22e022b5e032a2a9a19
6
+ metadata.gz: 1daf9219be0739e3ea92b59e285f4c0cba24684b97df0cc5bc0790f7a3d0947f46c22867b65b0d8392e7c3eebf7b5bb1edaffea298c9754fa3bde070c0baac88
7
+ data.tar.gz: 21f2abb512096ebc192e1d0f1c5e869f4b7c9032bed2d069ef2ed2bc400852bb85e3395cd1d92147b7227c2d222124bdad6f119f21142ec18d6a128508322dc6
@@ -1,15 +1,104 @@
1
- ## Rails 5.0.0.beta3 (February 24, 2016) ##
1
+ ## Rails 5.0.0.beta4 (April 27, 2016) ##
2
+
3
+ * Routing: Refactor `:action` default handling to ensure that path
4
+ parameters are not mutated during route generation.
5
+
6
+ *Andrew White*
7
+
8
+ * Add extension synonyms `yml` and `yaml` for MIME type `application/x-yaml`.
9
+
10
+ *bogdanvlviv*
2
11
 
3
- * Update session to have indifferent access across multiple requests.
12
+ * Adds support for including ActionController::Cookies in API controllers.
13
+ Previously, including the module would raise when trying to define
14
+ a `cookies` helper method. Skip calling #helper_method if it is not
15
+ defined -- if we don't have helpers, we needn't define one.
4
16
 
5
- session[:deep][:hash] = "Magic"
17
+ Fixes #24304
18
+
19
+ *Ryan T. Hosford*
20
+
21
+ * ETags: Introduce `Response#strong_etag=` and `#weak_etag=` and analogous
22
+ options for `fresh_when` and `stale?`. `Response#etag=` sets a weak ETag.
23
+
24
+ Strong ETags are desirable when you're serving byte-for-byte identical
25
+ responses that support Range requests, like PDFs or videos (typically
26
+ done by reproxying the response from a backend storage service).
27
+ Also desirable when fronted by some CDNs that support strong ETags
28
+ only, like Akamai.
29
+
30
+ *Jeremy Daer*
6
31
 
7
- session[:deep][:hash] == "Magic"
8
- session[:deep]["hash"] == "Magic"
32
+ * ETags: No longer strips quotes (") from ETag values before comparing them.
33
+ Quotes are significant, part of the ETag. A quoted ETag and an unquoted
34
+ one are not the same entity.
9
35
 
10
- *Tom Prats*
36
+ *Jeremy Daer*
37
+
38
+ * ETags: Support `If-None-Match: *`. Rarely useful for GET requests; meant
39
+ to provide some optimistic concurrency control for PUT requests.
40
+
41
+ *Jeremy Daer*
42
+
43
+ * `ActionDispatch::ParamsParser` is deprecated and was removed from the middleware
44
+ stack. To configure the parameter parsers use `ActionDispatch::Request.parameter_parsers=`.
45
+
46
+ *tenderlove*
47
+
48
+ * When a `respond_to` collector with a block doesn't have a response, then
49
+ a `:no_content` response should be rendered. This brings the default
50
+ rendering behavior introduced by https://github.com/rails/rails/issues/19036
51
+ to controller methods employing `respond_to`.
52
+
53
+ *Justin Coyne*
11
54
 
12
- * Add application/gzip as a default mime type.
55
+ * Add `ActionController::Parameters#dig` on Ruby 2.3 and greater, which
56
+ behaves the same as `Hash#dig`.
57
+
58
+ *Sean Griffin*
59
+
60
+ * Add request headers in the payload of the `start_processing.action_controller`
61
+ and `process_action.action_controller` notifications.
62
+
63
+ *Gareth du Plooy*
64
+
65
+ * Add `action_dispatch_integration_test` load hook. The hook can be used to
66
+ extend `ActionDispatch::IntegrationTest` once it has been loaded.
67
+
68
+ *Yuichiro Kaneko*
69
+
70
+ * Update default rendering policies when the controller action did
71
+ not explicitly indicate a response.
72
+
73
+ For API controllers, the implicit render always renders "204 No Content"
74
+ and does not account for any templates.
75
+
76
+ For other controllers, the following conditions are checked:
77
+
78
+ First, if a template exists for the controller action, it is rendered.
79
+ This template lookup takes into account the action name, locales, format,
80
+ variant, template handlers, etc. (see `render` for details).
81
+
82
+ Second, if other templates exist for the controller action but is not in
83
+ the right format (or variant, etc.), an `ActionController::UnknownFormat`
84
+ is raised. The list of available templates is assumed to be a complete
85
+ enumeration of all the possible formats (or variants, etc.); that is,
86
+ having only HTML and JSON templates indicate that the controller action is
87
+ not meant to handle XML requests.
88
+
89
+ Third, if the current request is an "interactive" browser request (the user
90
+ navigated here by entering the URL in the address bar, submitting a form,
91
+ clicking on a link, etc. as opposed to an XHR or non-browser API request),
92
+ `ActionView::UnknownFormat` is raised to display a helpful error
93
+ message.
94
+
95
+ Finally, it falls back to the same "204 No Content" behavior as API controllers.
96
+
97
+ *Godfrey Chan*, *Jon Moss*, *Kasper Timm Hansen*, *Mike Clark*, *Matthew Draper*
98
+
99
+ ## Rails 5.0.0.beta3 (February 24, 2016) ##
100
+
101
+ * Add "application/gzip" as a default mime type.
13
102
 
14
103
  *Mehmet Emin İNAÇ*
15
104
 
@@ -60,7 +149,7 @@
60
149
 
61
150
  *Kasper Timm Hansen*
62
151
 
63
- * Add image/svg+xml as a default mime type.
152
+ * Add "image/svg+xml" as a default mime type.
64
153
 
65
154
  *DHH*
66
155
 
@@ -73,7 +162,7 @@
73
162
 
74
163
  See #18902.
75
164
 
76
- *Anton Davydov* & *Vipul A M*
165
+ *Anton Davydov*, *Vipul A M*
77
166
 
78
167
  * Response etags to always be weak: Prefixes 'W/' to value returned by
79
168
  `ActionDispatch::Http::Cache::Response#etag=`, such that etags set in
@@ -105,11 +194,7 @@
105
194
 
106
195
  * Add option for per-form CSRF tokens.
107
196
 
108
- *Greg Ose & Ben Toews*
109
-
110
- * Add tests and documentation for `ActionController::Renderers::use_renderers`.
111
-
112
- *Benjamin Fleischer*
197
+ *Greg Ose*, *Ben Toews*
113
198
 
114
199
  * Fix `ActionController::Parameters#convert_parameters_to_hashes` to return filtered
115
200
  or unfiltered values based on from where it is called, `to_h` or `to_unsafe_h`
@@ -137,14 +222,14 @@
137
222
 
138
223
  *Derek Prior*
139
224
 
140
- * `ActionController::TestCase` will be moved to it's own gem in Rails 5.1
225
+ * `ActionController::TestCase` will be moved to its own gem in Rails 5.1.
141
226
 
142
227
  With the speed improvements made to `ActionDispatch::IntegrationTest` we no
143
228
  longer need to keep two separate code bases for testing controllers. In
144
229
  Rails 5.1 `ActionController::TestCase` will be deprecated and moved into a
145
230
  gem outside of Rails source.
146
231
 
147
- This is a documentation deprecation so that going forward so new tests will use
232
+ This is a documentation deprecation so that going forward new tests will use
148
233
  `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.
149
234
 
150
235
  *Eileen M. Uchitelle*
@@ -1,13 +1,11 @@
1
1
  require 'erubis'
2
+ require 'abstract_controller/error'
2
3
  require 'active_support/configurable'
3
4
  require 'active_support/descendants_tracker'
4
5
  require 'active_support/core_ext/module/anonymous'
5
6
  require 'active_support/core_ext/module/attr_internal'
6
7
 
7
8
  module AbstractController
8
- class Error < StandardError #:nodoc:
9
- end
10
-
11
9
  # Raised when a non-existing controller action is triggered.
12
10
  class ActionNotFound < StandardError
13
11
  end
@@ -78,7 +76,7 @@ module AbstractController
78
76
  end
79
77
  end
80
78
 
81
- # action_methods are cached and there is sometimes need to refresh
79
+ # action_methods are cached and there is sometimes a need to refresh
82
80
  # them. ::clear_action_methods! allows you to do that, so next time
83
81
  # you run action_methods, they will be recalculated.
84
82
  def clear_action_methods!
@@ -0,0 +1,4 @@
1
+ module AbstractController
2
+ class Error < StandardError #:nodoc:
3
+ end
4
+ end
@@ -38,7 +38,8 @@ module AbstractController
38
38
  end
39
39
 
40
40
  # Declare a controller method as a helper. For example, the following
41
- # makes the +current_user+ controller method available to the view:
41
+ # makes the +current_user+ and +logged_in?+ controller methods available
42
+ # to the view:
42
43
  # class ApplicationController < ActionController::Base
43
44
  # helper_method :current_user, :logged_in?
44
45
  #
@@ -1,3 +1,4 @@
1
+ require 'abstract_controller/error'
1
2
  require 'active_support/concern'
2
3
  require 'active_support/core_ext/class/attribute'
3
4
  require 'action_view'
@@ -14,22 +14,22 @@ module ActionController
14
14
  # flash, assets, and so on. This makes the entire controller stack thinner,
15
15
  # suitable for API applications. It doesn't mean you won't have such
16
16
  # features if you need them: they're all available for you to include in
17
- # your application, they're just not part of the default API Controller stack.
17
+ # your application, they're just not part of the default API controller stack.
18
18
  #
19
- # By default, only the ApplicationController in a \Rails application inherits
20
- # from <tt>ActionController::API</tt>. All other controllers in turn inherit
21
- # from ApplicationController.
19
+ # Normally, +ApplicationController+ is the only controller that inherits from
20
+ # <tt>ActionController::API</tt>. All other controllers in turn inherit from
21
+ # +ApplicationController+.
22
22
  #
23
23
  # A sample controller could look like this:
24
24
  #
25
25
  # class PostsController < ApplicationController
26
26
  # def index
27
- # @posts = Post.all
28
- # render json: @posts
27
+ # posts = Post.all
28
+ # render json: posts
29
29
  # end
30
30
  # end
31
31
  #
32
- # Request, response and parameters objects all work the exact same way as
32
+ # Request, response, and parameters objects all work the exact same way as
33
33
  # <tt>ActionController::Base</tt>.
34
34
  #
35
35
  # == Renders
@@ -37,18 +37,18 @@ module ActionController
37
37
  # The default API Controller stack includes all renderers, which means you
38
38
  # can use <tt>render :json</tt> and brothers freely in your controllers. Keep
39
39
  # in mind that templates are not going to be rendered, so you need to ensure
40
- # your controller is calling either <tt>render</tt> or <tt>redirect</tt> in
41
- # all actions, otherwise it will return 204 No Content response.
40
+ # your controller is calling either <tt>render</tt> or <tt>redirect_to</tt> in
41
+ # all actions, otherwise it will return 204 No Content.
42
42
  #
43
43
  # def show
44
- # @post = Post.find(params[:id])
45
- # render json: @post
44
+ # post = Post.find(params[:id])
45
+ # render json: post
46
46
  # end
47
47
  #
48
48
  # == Redirects
49
49
  #
50
50
  # Redirects are used to move from one action to another. You can use the
51
- # <tt>redirect</tt> method in your controllers in the same way as
51
+ # <tt>redirect_to</tt> method in your controllers in the same way as in
52
52
  # <tt>ActionController::Base</tt>. For example:
53
53
  #
54
54
  # def create
@@ -56,7 +56,7 @@ module ActionController
56
56
  # # do stuff here
57
57
  # end
58
58
  #
59
- # == Adding new behavior
59
+ # == Adding New Behavior
60
60
  #
61
61
  # In some scenarios you may want to add back some functionality provided by
62
62
  # <tt>ActionController::Base</tt> that is not present by default in
@@ -72,18 +72,19 @@ module ActionController
72
72
  #
73
73
  # class PostsController < ApplicationController
74
74
  # def index
75
- # @posts = Post.all
75
+ # posts = Post.all
76
76
  #
77
77
  # respond_to do |format|
78
- # format.json { render json: @posts }
79
- # format.xml { render xml: @posts }
78
+ # format.json { render json: posts }
79
+ # format.xml { render xml: posts }
80
80
  # end
81
81
  # end
82
82
  # end
83
83
  #
84
- # Quite straightforward. Make sure to check <tt>ActionController::Base</tt>
85
- # available modules if you want to include any other functionality that is
86
- # not provided by <tt>ActionController::API</tt> out of the box.
84
+ # Quite straightforward. Make sure to check the modules included in
85
+ # <tt>ActionController::Base</tt> if you want to use any other
86
+ # functionality that is not provided by <tt>ActionController::API</tt>
87
+ # out of the box.
87
88
  class API < Metal
88
89
  abstract!
89
90
 
@@ -1,5 +1,5 @@
1
1
  module ActionController
2
- module BasicImplicitRender
2
+ module BasicImplicitRender # :nodoc:
3
3
  def send_action(method, *args)
4
4
  super.tap { default_render unless performed? }
5
5
  end
@@ -36,8 +36,23 @@ module ActionController
36
36
  #
37
37
  # === Parameters:
38
38
  #
39
- # * <tt>:etag</tt>.
40
- # * <tt>:last_modified</tt>.
39
+ # * <tt>:etag</tt> Sets a "weak" ETag validator on the response. See the
40
+ # +:weak_etag+ option.
41
+ # * <tt>:weak_etag</tt> Sets a "weak" ETag validator on the response.
42
+ # Requests that set If-None-Match header may return a 304 Not Modified
43
+ # response if it matches the ETag exactly. A weak ETag indicates semantic
44
+ # equivalence, not byte-for-byte equality, so they're good for caching
45
+ # HTML pages in browser caches. They can't be used for responses that
46
+ # must be byte-identical, like serving Range requests within a PDF file.
47
+ # * <tt>:strong_etag</tt> Sets a "strong" ETag validator on the response.
48
+ # Requests that set If-None-Match header may return a 304 Not Modified
49
+ # response if it matches the ETag exactly. A strong ETag implies exact
50
+ # equality: the response must match byte for byte. This is necessary for
51
+ # doing Range requests within a large video or PDF file, for example, or
52
+ # for compatibility with some CDNs that don't support weak ETags.
53
+ # * <tt>:last_modified</tt> Sets a "weak" last-update validator on the
54
+ # response. Subsequent requests that set If-Modified-Since may return a
55
+ # 304 Not Modified response if last_modified <= If-Modified-Since.
41
56
  # * <tt>:public</tt> By default the Cache-Control header is private, set this to
42
57
  # +true+ if you want your application to be cacheable by other devices (proxy caches).
43
58
  # * <tt>:template</tt> By default, the template digest for the current
@@ -86,12 +101,16 @@ module ActionController
86
101
  #
87
102
  # before_action { fresh_when @article, template: 'widgets/show' }
88
103
  #
89
- def fresh_when(object = nil, etag: object, last_modified: nil, public: false, template: nil)
104
+ def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, template: nil)
105
+ weak_etag ||= etag || object unless strong_etag
90
106
  last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
91
107
 
92
- if etag || template
93
- response.etag = combine_etags(etag: etag, last_modified: last_modified,
94
- public: public, template: template)
108
+ if strong_etag
109
+ response.strong_etag = combine_etags strong_etag,
110
+ last_modified: last_modified, public: public, template: template
111
+ elsif weak_etag || template
112
+ response.weak_etag = combine_etags weak_etag,
113
+ last_modified: last_modified, public: public, template: template
95
114
  end
96
115
 
97
116
  response.last_modified = last_modified if last_modified
@@ -107,8 +126,23 @@ module ActionController
107
126
  #
108
127
  # === Parameters:
109
128
  #
110
- # * <tt>:etag</tt>.
111
- # * <tt>:last_modified</tt>.
129
+ # * <tt>:etag</tt> Sets a "weak" ETag validator on the response. See the
130
+ # +:weak_etag+ option.
131
+ # * <tt>:weak_etag</tt> Sets a "weak" ETag validator on the response.
132
+ # requests that set If-None-Match header may return a 304 Not Modified
133
+ # response if it matches the ETag exactly. A weak ETag indicates semantic
134
+ # equivalence, not byte-for-byte equality, so they're good for caching
135
+ # HTML pages in browser caches. They can't be used for responses that
136
+ # must be byte-identical, like serving Range requests within a PDF file.
137
+ # * <tt>:strong_etag</tt> Sets a "strong" ETag validator on the response.
138
+ # Requests that set If-None-Match header may return a 304 Not Modified
139
+ # response if it matches the ETag exactly. A strong ETag implies exact
140
+ # equality: the response must match byte for byte. This is necessary for
141
+ # doing Range requests within a large video or PDF file, for example, or
142
+ # for compatibility with some CDNs that don't support weak ETags.
143
+ # * <tt>:last_modified</tt> Sets a "weak" last-update validator on the
144
+ # response. Subsequent requests that set If-Modified-Since may return a
145
+ # 304 Not Modified response if last_modified <= If-Modified-Since.
112
146
  # * <tt>:public</tt> By default the Cache-Control header is private, set this to
113
147
  # +true+ if you want your application to be cacheable by other devices (proxy caches).
114
148
  # * <tt>:template</tt> By default, the template digest for the current
@@ -180,12 +214,12 @@ module ActionController
180
214
  # super if stale? @article, template: 'widgets/show'
181
215
  # end
182
216
  #
183
- def stale?(object = nil, etag: object, last_modified: nil, public: nil, template: nil)
184
- fresh_when(object, etag: etag, last_modified: last_modified, public: public, template: template)
217
+ def stale?(object = nil, **freshness_kwargs)
218
+ fresh_when(object, **freshness_kwargs)
185
219
  !request.fresh?(response)
186
220
  end
187
221
 
188
- # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a +private+
222
+ # Sets an HTTP 1.1 Cache-Control header. Defaults to issuing a +private+
189
223
  # instruction, so that intermediate caches must not cache the response.
190
224
  #
191
225
  # expires_in 20.minutes
@@ -195,7 +229,7 @@ module ActionController
195
229
  # This method will overwrite an existing Cache-Control header.
196
230
  # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
197
231
  #
198
- # The method will also ensure a HTTP Date header for client compatibility.
232
+ # The method will also ensure an HTTP Date header for client compatibility.
199
233
  def expires_in(seconds, options = {})
200
234
  response.cache_control.merge!(
201
235
  :max_age => seconds,
@@ -208,7 +242,7 @@ module ActionController
208
242
  response.date = Time.now unless response.date?
209
243
  end
210
244
 
211
- # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should
245
+ # Sets an HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should
212
246
  # occur by the browser or intermediate caches (like caching proxy servers).
213
247
  def expires_now
214
248
  response.cache_control.replace(:no_cache => true)
@@ -216,26 +250,23 @@ module ActionController
216
250
 
217
251
  # Cache or yield the block. The cache is supposed to never expire.
218
252
  #
219
- # You can use this method when you have a HTTP response that never changes,
253
+ # You can use this method when you have an HTTP response that never changes,
220
254
  # and the browser and proxies should cache it indefinitely.
221
255
  #
222
256
  # * +public+: By default, HTTP responses are private, cached only on the
223
257
  # user's web browser. To allow proxies to cache the response, set +true+ to
224
258
  # indicate that they can serve the cached response to all users.
225
- #
226
- # * +version+: the version passed as a key for the cache.
227
- def http_cache_forever(public: false, version: 'v1')
259
+ def http_cache_forever(public: false)
228
260
  expires_in 100.years, public: public
229
261
 
230
- yield if stale?(etag: "#{version}-#{request.fullpath}",
262
+ yield if stale?(etag: request.fullpath,
231
263
  last_modified: Time.new(2011, 1, 1).utc,
232
264
  public: public)
233
265
  end
234
266
 
235
267
  private
236
- def combine_etags(options)
237
- etags = etaggers.map { |etagger| instance_exec(options, &etagger) }.compact
238
- etags.unshift options[:etag]
268
+ def combine_etags(validator, options)
269
+ [validator, *etaggers.map { |etagger| instance_exec(options, &etagger) }].compact
239
270
  end
240
271
  end
241
272
  end
@@ -3,7 +3,7 @@ module ActionController #:nodoc:
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- helper_method :cookies
6
+ helper_method :cookies if defined?(helper_method)
7
7
  end
8
8
 
9
9
  private