actionpack 2.3.4 → 2.3.5
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.
- data/CHANGELOG +12 -0
- data/Rakefile +1 -1
- data/lib/action_controller.rb +3 -1
- data/lib/action_controller/assertions/dom_assertions.rb +19 -3
- data/lib/action_controller/assertions/selector_assertions.rb +16 -10
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/caching.rb +1 -0
- data/lib/action_controller/cookies.rb +2 -1
- data/lib/action_controller/http_authentication.rb +3 -2
- data/lib/action_controller/integration.rb +15 -3
- data/lib/action_controller/layout.rb +6 -1
- data/lib/action_controller/middlewares.rb +2 -0
- data/lib/action_controller/polymorphic_routes.rb +6 -21
- data/lib/action_controller/rack_lint_patch.rb +36 -0
- data/lib/action_controller/request_forgery_protection.rb +6 -2
- data/lib/action_controller/response.rb +2 -1
- data/lib/action_controller/string_coercion.rb +29 -0
- data/lib/action_controller/test_case.rb +6 -1
- data/lib/action_controller/test_process.rb +1 -1
- data/lib/action_controller/translation.rb +2 -2
- data/lib/action_controller/uploaded_file.rb +2 -2
- data/lib/action_controller/vendor/html-scanner/html/node.rb +1 -1
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +3 -3
- data/lib/action_view/base.rb +6 -1
- data/lib/action_view/erb/util.rb +6 -0
- data/lib/action_view/helpers.rb +2 -0
- data/lib/action_view/helpers/active_record_helper.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +2 -2
- data/lib/action_view/helpers/capture_helper.rb +2 -2
- data/lib/action_view/helpers/date_helper.rb +27 -15
- data/lib/action_view/helpers/form_helper.rb +32 -11
- data/lib/action_view/helpers/form_options_helper.rb +1 -1
- data/lib/action_view/helpers/form_tag_helper.rb +3 -3
- data/lib/action_view/helpers/number_helper.rb +6 -1
- data/lib/action_view/helpers/prototype_helper.rb +1 -1
- data/lib/action_view/helpers/raw_output_helper.rb +9 -0
- data/lib/action_view/helpers/sanitize_helper.rb +10 -2
- data/lib/action_view/helpers/tag_helper.rb +4 -4
- data/lib/action_view/helpers/translation_helper.rb +1 -1
- data/lib/action_view/helpers/url_helper.rb +3 -3
- data/lib/action_view/locale/en.yml +3 -0
- data/lib/action_view/partials.rb +1 -1
- data/lib/action_view/safe_buffer.rb +28 -0
- data/lib/action_view/template.rb +8 -2
- data/lib/action_view/test_case.rb +102 -27
- data/lib/actionpack.rb +1 -0
- data/test/controller/cookie_test.rb +7 -0
- data/test/controller/dom_assertions_test.rb +53 -0
- data/test/controller/filter_params_test.rb +1 -0
- data/test/controller/html-scanner/sanitizer_test.rb +1 -0
- data/test/controller/http_digest_authentication_test.rb +22 -0
- data/test/controller/integration_test.rb +38 -0
- data/test/controller/layout_test.rb +11 -0
- data/test/controller/polymorphic_routes_test.rb +4 -0
- data/test/controller/request_forgery_protection_test.rb +19 -1
- data/test/controller/routing_test.rb +23 -15
- data/test/controller/session/test_session_test.rb +2 -2
- data/test/fixtures/layout_tests/abs_path_layout.rhtml +1 -0
- data/test/fixtures/test/_from_helper.erb +1 -0
- data/test/template/active_record_helper_test.rb +1 -1
- data/test/template/asset_tag_helper_test.rb +12 -0
- data/test/template/benchmark_helper_test.rb +6 -6
- data/test/template/compiled_templates_test.rb +2 -1
- data/test/template/date_helper_i18n_test.rb +10 -9
- data/test/template/date_helper_test.rb +29 -13
- data/test/template/form_helper_test.rb +90 -10
- data/test/template/number_helper_test.rb +4 -0
- data/test/template/raw_output_helper_test.rb +21 -0
- data/test/template/sanitize_helper_test.rb +10 -1
- data/test/template/tag_helper_test.rb +1 -0
- data/test/view/safe_buffer_test.rb +36 -0
- data/test/view/test_case_test.rb +173 -5
- metadata +13 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
*2.3.5 (November 25, 2009)*
|
2
|
+
|
3
|
+
* Minor Bug Fixes and deprecation warnings
|
4
|
+
|
5
|
+
* Ruby 1.9 Support
|
6
|
+
|
7
|
+
* Fix filtering parameters when there are Fixnum or other un-dupable values.
|
8
|
+
|
9
|
+
* Improvements to ActionView::TestCase
|
10
|
+
|
11
|
+
* Compatiblity with the rails_xss plugin
|
12
|
+
|
1
13
|
*2.3.4 (September 4, 2009)*
|
2
14
|
|
3
15
|
* Sanitize multibyte strings before escaping them with escape_once. CVE-2009-3009
|
data/Rakefile
CHANGED
@@ -79,7 +79,7 @@ spec = Gem::Specification.new do |s|
|
|
79
79
|
s.has_rdoc = true
|
80
80
|
s.requirements << 'none'
|
81
81
|
|
82
|
-
s.add_dependency('activesupport', '= 2.3.
|
82
|
+
s.add_dependency('activesupport', '= 2.3.5' + PKG_BUILD)
|
83
83
|
s.add_dependency('rack', '~> 1.0.0')
|
84
84
|
|
85
85
|
s.require_path = 'lib'
|
data/lib/action_controller.rb
CHANGED
@@ -31,8 +31,9 @@ rescue LoadError
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
gem 'rack', '~> 1.0.
|
34
|
+
gem 'rack', '~> 1.0.1'
|
35
35
|
require 'rack'
|
36
|
+
require 'action_controller/cgi_ext'
|
36
37
|
|
37
38
|
module ActionController
|
38
39
|
# TODO: Review explicit to see if they will automatically be handled by
|
@@ -70,6 +71,7 @@ module ActionController
|
|
70
71
|
autoload :SessionManagement, 'action_controller/session_management'
|
71
72
|
autoload :StatusCodes, 'action_controller/status_codes'
|
72
73
|
autoload :Streaming, 'action_controller/streaming'
|
74
|
+
autoload :StringCoercion, 'action_controller/string_coercion'
|
73
75
|
autoload :TestCase, 'action_controller/test_case'
|
74
76
|
autoload :TestProcess, 'action_controller/test_process'
|
75
77
|
autoload :Translation, 'action_controller/translation'
|
@@ -1,6 +1,18 @@
|
|
1
1
|
module ActionController
|
2
2
|
module Assertions
|
3
3
|
module DomAssertions
|
4
|
+
def self.strip_whitespace!(nodes)
|
5
|
+
nodes.reject! do |node|
|
6
|
+
if node.is_a?(HTML::Text)
|
7
|
+
node.content.strip!
|
8
|
+
node.content.empty?
|
9
|
+
else
|
10
|
+
strip_whitespace! node.children
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
4
16
|
# Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
|
5
17
|
#
|
6
18
|
# ==== Examples
|
@@ -12,13 +24,15 @@ module ActionController
|
|
12
24
|
clean_backtrace do
|
13
25
|
expected_dom = HTML::Document.new(expected).root
|
14
26
|
actual_dom = HTML::Document.new(actual).root
|
15
|
-
|
27
|
+
DomAssertions.strip_whitespace!(expected_dom.children)
|
28
|
+
DomAssertions.strip_whitespace!(actual_dom.children)
|
16
29
|
|
30
|
+
full_message = build_message(message, "<?> expected but was\n<?>.", expected_dom.to_s, actual_dom.to_s)
|
17
31
|
assert_block(full_message) { expected_dom == actual_dom }
|
18
32
|
end
|
19
33
|
end
|
20
34
|
|
21
|
-
# The negated form of +
|
35
|
+
# The negated form of +assert_dom_equal+.
|
22
36
|
#
|
23
37
|
# ==== Examples
|
24
38
|
#
|
@@ -29,8 +43,10 @@ module ActionController
|
|
29
43
|
clean_backtrace do
|
30
44
|
expected_dom = HTML::Document.new(expected).root
|
31
45
|
actual_dom = HTML::Document.new(actual).root
|
32
|
-
|
46
|
+
DomAssertions.strip_whitespace!(expected_dom.children)
|
47
|
+
DomAssertions.strip_whitespace!(actual_dom.children)
|
33
48
|
|
49
|
+
full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s)
|
34
50
|
assert_block(full_message) { expected_dom != actual_dom }
|
35
51
|
end
|
36
52
|
end
|
@@ -16,7 +16,7 @@ module ActionController
|
|
16
16
|
#
|
17
17
|
# Use +css_select+ to select elements without making an assertions, either
|
18
18
|
# from the response HTML or elements selected by the enclosing assertion.
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# In addition to HTML responses, you can make the following assertions:
|
21
21
|
# * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations.
|
22
22
|
# * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
|
@@ -24,6 +24,12 @@ module ActionController
|
|
24
24
|
#
|
25
25
|
# Also see HTML::Selector to learn how to use selectors.
|
26
26
|
module SelectorAssertions
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
@selected = nil
|
31
|
+
end
|
32
|
+
|
27
33
|
# :call-seq:
|
28
34
|
# css_select(selector) => array
|
29
35
|
# css_select(element, selector) => array
|
@@ -53,8 +59,8 @@ module ActionController
|
|
53
59
|
# end
|
54
60
|
#
|
55
61
|
# # Selects all list items in unordered lists
|
56
|
-
# items = css_select("ul>li")
|
57
|
-
#
|
62
|
+
# items = css_select("ul>li")
|
63
|
+
#
|
58
64
|
# # Selects all form tags and then all inputs inside the form
|
59
65
|
# forms = css_select("form")
|
60
66
|
# forms.each do |form|
|
@@ -212,7 +218,7 @@ module ActionController
|
|
212
218
|
# Otherwise just operate on the response document.
|
213
219
|
root = response_from_page_or_rjs
|
214
220
|
end
|
215
|
-
|
221
|
+
|
216
222
|
# First or second argument is the selector: string and we pass
|
217
223
|
# all remaining arguments. Array and we pass the argument. Also
|
218
224
|
# accepts selector itself.
|
@@ -225,7 +231,7 @@ module ActionController
|
|
225
231
|
selector = arg
|
226
232
|
else raise ArgumentError, "Expecting a selector as the first argument"
|
227
233
|
end
|
228
|
-
|
234
|
+
|
229
235
|
# Next argument is used for equality tests.
|
230
236
|
equals = {}
|
231
237
|
case arg = args.shift
|
@@ -315,10 +321,10 @@ module ActionController
|
|
315
321
|
# Returns all matches elements.
|
316
322
|
matches
|
317
323
|
end
|
318
|
-
|
324
|
+
|
319
325
|
def count_description(min, max) #:nodoc:
|
320
326
|
pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')}
|
321
|
-
|
327
|
+
|
322
328
|
if min && max && (max != min)
|
323
329
|
"between #{min} and #{max} elements"
|
324
330
|
elsif min && !(min == 1 && max == 1)
|
@@ -327,7 +333,7 @@ module ActionController
|
|
327
333
|
"at most #{max} #{pluralize['element', max]}"
|
328
334
|
end
|
329
335
|
end
|
330
|
-
|
336
|
+
|
331
337
|
# :call-seq:
|
332
338
|
# assert_select_rjs(id?) { |elements| ... }
|
333
339
|
# assert_select_rjs(statement, id?) { |elements| ... }
|
@@ -344,7 +350,7 @@ module ActionController
|
|
344
350
|
# that update or insert an element with that identifier.
|
345
351
|
#
|
346
352
|
# Use the first argument to narrow down assertions to only statements
|
347
|
-
# of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>,
|
353
|
+
# of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>,
|
348
354
|
# <tt>:show</tt>, <tt>:hide</tt>, <tt>:toggle</tt>, <tt>:remove</tt> and
|
349
355
|
# <tt>:insert_html</tt>.
|
350
356
|
#
|
@@ -488,7 +494,7 @@ module ActionController
|
|
488
494
|
# end
|
489
495
|
# end
|
490
496
|
# end
|
491
|
-
#
|
497
|
+
#
|
492
498
|
#
|
493
499
|
# # Selects all paragraph tags from within the description of an RSS feed
|
494
500
|
# assert_select_feed :rss, 2.0 do
|
@@ -22,6 +22,7 @@ module ActionController #:nodoc:
|
|
22
22
|
# ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
|
23
23
|
# ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
|
24
24
|
# ActionController::Base.cache_store = :mem_cache_store, "localhost"
|
25
|
+
# ActionController::Base.cache_store = :mem_cache_store, Memcached::Rails.new("localhost:11211")
|
25
26
|
# ActionController::Base.cache_store = MyOwnStore.new("parameter")
|
26
27
|
module Caching
|
27
28
|
autoload :Actions, 'action_controller/caching/actions'
|
@@ -87,8 +87,9 @@ module ActionController #:nodoc:
|
|
87
87
|
def delete(key, options = {})
|
88
88
|
options.symbolize_keys!
|
89
89
|
options[:path] = "/" unless options.has_key?(:path)
|
90
|
-
super(key.to_s)
|
90
|
+
value = super(key.to_s)
|
91
91
|
@controller.response.delete_cookie(key, options)
|
92
|
+
value
|
92
93
|
end
|
93
94
|
end
|
94
95
|
end
|
@@ -227,9 +227,9 @@ module ActionController
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def decode_credentials(header)
|
230
|
-
header.to_s.gsub(/^Digest\s+/,'').split(',').inject({}) do |hash, pair|
|
230
|
+
header.to_s.gsub(/^Digest\s+/,'').split(',').inject({}.with_indifferent_access) do |hash, pair|
|
231
231
|
key, value = pair.split('=', 2)
|
232
|
-
hash[key.strip
|
232
|
+
hash[key.strip] = value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')
|
233
233
|
hash
|
234
234
|
end
|
235
235
|
end
|
@@ -289,6 +289,7 @@ module ActionController
|
|
289
289
|
# allow a user to use new nonce without prompting user again for their
|
290
290
|
# username and password.
|
291
291
|
def validate_nonce(request, value, seconds_to_timeout=5*60)
|
292
|
+
return false if value.nil?
|
292
293
|
t = Base64.decode64(value).split(":").first.to_i
|
293
294
|
nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
|
294
295
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
require 'uri'
|
3
3
|
require 'active_support/test_case'
|
4
|
+
require 'action_controller/rack_lint_patch'
|
4
5
|
|
5
6
|
module ActionController
|
6
7
|
module Integration #:nodoc:
|
@@ -268,7 +269,9 @@ module ActionController
|
|
268
269
|
|
269
270
|
env["QUERY_STRING"] ||= ""
|
270
271
|
|
271
|
-
data
|
272
|
+
data ||= ''
|
273
|
+
data.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
|
274
|
+
data = data.is_a?(IO) ? data : StringIO.new(data)
|
272
275
|
|
273
276
|
env.update(
|
274
277
|
"REQUEST_METHOD" => method.to_s.upcase,
|
@@ -476,6 +479,11 @@ EOF
|
|
476
479
|
end
|
477
480
|
|
478
481
|
module Runner
|
482
|
+
def initialize(*args)
|
483
|
+
super
|
484
|
+
@integration_session = nil
|
485
|
+
end
|
486
|
+
|
479
487
|
# Reset the current session. This is useful for testing multiple sessions
|
480
488
|
# in a single test case.
|
481
489
|
def reset!
|
@@ -543,8 +551,12 @@ EOF
|
|
543
551
|
# Delegate unhandled messages to the current session instance.
|
544
552
|
def method_missing(sym, *args, &block)
|
545
553
|
reset! unless @integration_session
|
546
|
-
|
547
|
-
|
554
|
+
if @integration_session.respond_to?(sym)
|
555
|
+
returning @integration_session.__send__(sym, *args, &block) do
|
556
|
+
copy_session_variables!
|
557
|
+
end
|
558
|
+
else
|
559
|
+
super
|
548
560
|
end
|
549
561
|
end
|
550
562
|
end
|
@@ -194,6 +194,11 @@ module ActionController #:nodoc:
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
+
def initialize(*args)
|
198
|
+
super
|
199
|
+
@real_format = nil
|
200
|
+
end
|
201
|
+
|
197
202
|
# Returns the name of the active layout. If the layout was specified as a method reference (through a symbol), this method
|
198
203
|
# is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method
|
199
204
|
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
|
@@ -221,7 +226,7 @@ module ActionController #:nodoc:
|
|
221
226
|
end
|
222
227
|
|
223
228
|
def find_layout(layout, format, html_fallback=false) #:nodoc:
|
224
|
-
view_paths.find_template(layout.to_s =~
|
229
|
+
view_paths.find_template(layout.to_s =~ /\A\/|layouts\// ? layout : "layouts/#{layout}", format, html_fallback)
|
225
230
|
rescue ActionView::MissingTemplate
|
226
231
|
raise if Mime::Type.lookup_by_extension(format.to_s).html?
|
227
232
|
end
|
@@ -76,8 +76,7 @@ module ActionController
|
|
76
76
|
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
|
77
77
|
end
|
78
78
|
|
79
|
-
record
|
80
|
-
namespace = extract_namespace(record_or_hash_or_array)
|
79
|
+
record = extract_record(record_or_hash_or_array)
|
81
80
|
|
82
81
|
args = case record_or_hash_or_array
|
83
82
|
when Hash; [ record_or_hash_or_array ]
|
@@ -98,8 +97,7 @@ module ActionController
|
|
98
97
|
end
|
99
98
|
|
100
99
|
args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
|
101
|
-
|
102
|
-
named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
|
100
|
+
named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
|
103
101
|
|
104
102
|
url_options = options.except(:action, :routing_type)
|
105
103
|
unless url_options.empty?
|
@@ -153,7 +151,7 @@ module ActionController
|
|
153
151
|
options[:routing_type] || :url
|
154
152
|
end
|
155
153
|
|
156
|
-
def build_named_route_call(records,
|
154
|
+
def build_named_route_call(records, inflection, options = {})
|
157
155
|
unless records.is_a?(Array)
|
158
156
|
record = extract_record(records)
|
159
157
|
route = ''
|
@@ -163,7 +161,7 @@ module ActionController
|
|
163
161
|
if parent.is_a?(Symbol) || parent.is_a?(String)
|
164
162
|
string << "#{parent}_"
|
165
163
|
else
|
166
|
-
string <<
|
164
|
+
string << RecordIdentifier.__send__("plural_class_name", parent).singularize
|
167
165
|
string << "_"
|
168
166
|
end
|
169
167
|
end
|
@@ -172,12 +170,12 @@ module ActionController
|
|
172
170
|
if record.is_a?(Symbol) || record.is_a?(String)
|
173
171
|
route << "#{record}_"
|
174
172
|
else
|
175
|
-
route <<
|
173
|
+
route << RecordIdentifier.__send__("plural_class_name", record)
|
176
174
|
route = route.singularize if inflection == :singular
|
177
175
|
route << "_"
|
178
176
|
end
|
179
177
|
|
180
|
-
action_prefix(options) +
|
178
|
+
action_prefix(options) + route + routing_type(options).to_s
|
181
179
|
end
|
182
180
|
|
183
181
|
def extract_record(record_or_hash_or_array)
|
@@ -187,18 +185,5 @@ module ActionController
|
|
187
185
|
else record_or_hash_or_array
|
188
186
|
end
|
189
187
|
end
|
190
|
-
|
191
|
-
# Remove the first symbols from the array and return the url prefix
|
192
|
-
# implied by those symbols.
|
193
|
-
def extract_namespace(record_or_hash_or_array)
|
194
|
-
return "" unless record_or_hash_or_array.is_a?(Array)
|
195
|
-
|
196
|
-
namespace_keys = []
|
197
|
-
while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol)
|
198
|
-
namespace_keys << record_or_hash_or_array.shift
|
199
|
-
end
|
200
|
-
|
201
|
-
namespace_keys.map {|k| "#{k}_"}.join
|
202
|
-
end
|
203
188
|
end
|
204
189
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Rack 1.0 does not allow string subclass body. This does not play well with our ActionView::SafeBuffer.
|
2
|
+
# The next release of Rack will be allowing string subclass body - http://github.com/rack/rack/commit/de668df02802a0335376a81ba709270e43ba9d55
|
3
|
+
# TODO : Remove this monkey patch after the next release of Rack
|
4
|
+
|
5
|
+
module RackLintPatch
|
6
|
+
module AllowStringSubclass
|
7
|
+
def self.included(base)
|
8
|
+
base.send :alias_method, :each, :each_with_hack
|
9
|
+
end
|
10
|
+
|
11
|
+
def each_with_hack
|
12
|
+
@closed = false
|
13
|
+
|
14
|
+
@body.each { |part|
|
15
|
+
assert("Body yielded non-string value #{part.inspect}") {
|
16
|
+
part.kind_of?(String)
|
17
|
+
}
|
18
|
+
yield part
|
19
|
+
}
|
20
|
+
|
21
|
+
if @body.respond_to?(:to_path)
|
22
|
+
assert("The file identified by body.to_path does not exist") {
|
23
|
+
::File.exist? @body.to_path
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
app = proc {|env| [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, [Class.new(String).new("Hello World!")]] }
|
31
|
+
response = Rack::MockRequest.new(Rack::Lint.new(app)).get('/')
|
32
|
+
rescue Rack::Lint::LintError => e
|
33
|
+
raise(e) unless e.message =~ /Body yielded non-string value/
|
34
|
+
Rack::Lint.send :include, AllowStringSubclass
|
35
|
+
end
|
36
|
+
end
|
@@ -89,9 +89,13 @@ module ActionController #:nodoc:
|
|
89
89
|
request.method == :get ||
|
90
90
|
request.xhr? ||
|
91
91
|
!verifiable_request_format? ||
|
92
|
-
form_authenticity_token ==
|
92
|
+
form_authenticity_token == form_authenticity_param
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
|
+
def form_authenticity_param
|
96
|
+
params[request_forgery_protection_token]
|
97
|
+
end
|
98
|
+
|
95
99
|
def verifiable_request_format?
|
96
100
|
!request.content_type.nil? && request.content_type.verify_request?
|
97
101
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActionController
|
2
|
+
class StringCoercion
|
3
|
+
class UglyBody < ActiveSupport::BasicObject
|
4
|
+
def initialize(body)
|
5
|
+
@body = body
|
6
|
+
end
|
7
|
+
|
8
|
+
def each
|
9
|
+
@body.each do |part|
|
10
|
+
yield part.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def method_missing(*args, &block)
|
16
|
+
@body.__send__(*args, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(app)
|
21
|
+
@app = app
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(env)
|
25
|
+
status, headers, body = @app.call(env)
|
26
|
+
[status, headers, UglyBody.new(body)]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|