actionpack 4.0.0.beta1 → 4.0.0.rc1

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +195 -11
  3. data/lib/abstract_controller/base.rb +1 -1
  4. data/lib/abstract_controller/helpers.rb +2 -2
  5. data/lib/abstract_controller/layouts.rb +10 -5
  6. data/lib/abstract_controller/rendering.rb +11 -3
  7. data/lib/abstract_controller/translation.rb +1 -1
  8. data/lib/action_controller/log_subscriber.rb +5 -0
  9. data/lib/action_controller/metal.rb +2 -3
  10. data/lib/action_controller/metal/force_ssl.rb +52 -17
  11. data/lib/action_controller/metal/helpers.rb +0 -1
  12. data/lib/action_controller/metal/hide_actions.rb +1 -1
  13. data/lib/action_controller/metal/http_authentication.rb +3 -2
  14. data/lib/action_controller/metal/live.rb +34 -0
  15. data/lib/action_controller/metal/rendering.rb +1 -1
  16. data/lib/action_controller/metal/strong_parameters.rb +7 -3
  17. data/lib/action_controller/test_case.rb +45 -11
  18. data/lib/action_dispatch.rb +4 -6
  19. data/lib/action_dispatch/http/cache.rb +2 -2
  20. data/lib/action_dispatch/http/headers.rb +39 -15
  21. data/lib/action_dispatch/http/mime_negotiation.rb +1 -1
  22. data/lib/action_dispatch/http/mime_type.rb +11 -3
  23. data/lib/action_dispatch/http/parameters.rb +17 -24
  24. data/lib/action_dispatch/http/request.rb +17 -2
  25. data/lib/action_dispatch/http/response.rb +2 -1
  26. data/lib/action_dispatch/http/upload.rb +5 -5
  27. data/lib/action_dispatch/http/url.rb +53 -12
  28. data/lib/action_dispatch/journey/formatter.rb +1 -1
  29. data/lib/action_dispatch/journey/path/pattern.rb +1 -1
  30. data/lib/action_dispatch/journey/route.rb +8 -0
  31. data/lib/action_dispatch/journey/router.rb +3 -1
  32. data/lib/action_dispatch/journey/visitors.rb +8 -0
  33. data/lib/action_dispatch/middleware/cookies.rb +169 -135
  34. data/lib/action_dispatch/middleware/exception_wrapper.rb +1 -0
  35. data/lib/action_dispatch/middleware/remote_ip.rb +2 -2
  36. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  37. data/lib/action_dispatch/middleware/session/cookie_store.rb +38 -58
  38. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
  39. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +4 -6
  40. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +1 -1
  41. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +1 -1
  42. data/lib/action_dispatch/routing.rb +28 -64
  43. data/lib/action_dispatch/routing/mapper.rb +61 -48
  44. data/lib/action_dispatch/routing/route_set.rb +17 -14
  45. data/lib/action_dispatch/testing/assertions/routing.rb +2 -2
  46. data/lib/action_dispatch/testing/assertions/selector.rb +2 -2
  47. data/lib/action_dispatch/testing/integration.rb +36 -35
  48. data/lib/action_dispatch/testing/test_process.rb +1 -1
  49. data/lib/action_pack/version.rb +7 -6
  50. data/lib/action_view/buffers.rb +6 -0
  51. data/lib/action_view/dependency_tracker.rb +3 -1
  52. data/lib/action_view/helpers/asset_tag_helper.rb +13 -8
  53. data/lib/action_view/helpers/capture_helper.rb +2 -2
  54. data/lib/action_view/helpers/date_helper.rb +1 -1
  55. data/lib/action_view/helpers/form_helper.rb +56 -19
  56. data/lib/action_view/helpers/form_options_helper.rb +3 -3
  57. data/lib/action_view/helpers/form_tag_helper.rb +1 -1
  58. data/lib/action_view/helpers/javascript_helper.rb +2 -2
  59. data/lib/action_view/helpers/number_helper.rb +25 -0
  60. data/lib/action_view/helpers/tags/base.rb +9 -10
  61. data/lib/action_view/helpers/tags/check_box.rb +1 -1
  62. data/lib/action_view/helpers/tags/checkable.rb +2 -2
  63. data/lib/action_view/helpers/tags/collection_check_boxes.rb +3 -3
  64. data/lib/action_view/helpers/tags/collection_helpers.rb +3 -3
  65. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +3 -3
  66. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  67. data/lib/action_view/helpers/tags/color_field.rb +2 -2
  68. data/lib/action_view/helpers/tags/date_field.rb +2 -2
  69. data/lib/action_view/helpers/tags/date_select.rb +2 -2
  70. data/lib/action_view/helpers/tags/datetime_field.rb +2 -2
  71. data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -2
  72. data/lib/action_view/helpers/tags/datetime_select.rb +2 -2
  73. data/lib/action_view/helpers/tags/email_field.rb +2 -2
  74. data/lib/action_view/helpers/tags/file_field.rb +2 -2
  75. data/lib/action_view/helpers/tags/grouped_collection_select.rb +2 -2
  76. data/lib/action_view/helpers/tags/hidden_field.rb +2 -2
  77. data/lib/action_view/helpers/tags/label.rb +2 -2
  78. data/lib/action_view/helpers/tags/month_field.rb +2 -2
  79. data/lib/action_view/helpers/tags/number_field.rb +2 -2
  80. data/lib/action_view/helpers/tags/password_field.rb +2 -2
  81. data/lib/action_view/helpers/tags/radio_button.rb +2 -2
  82. data/lib/action_view/helpers/tags/range_field.rb +2 -2
  83. data/lib/action_view/helpers/tags/search_field.rb +2 -2
  84. data/lib/action_view/helpers/tags/select.rb +2 -3
  85. data/lib/action_view/helpers/tags/tel_field.rb +2 -2
  86. data/lib/action_view/helpers/tags/text_area.rb +2 -2
  87. data/lib/action_view/helpers/tags/text_field.rb +2 -2
  88. data/lib/action_view/helpers/tags/time_field.rb +2 -2
  89. data/lib/action_view/helpers/tags/time_select.rb +2 -2
  90. data/lib/action_view/helpers/tags/time_zone_select.rb +2 -2
  91. data/lib/action_view/helpers/tags/url_field.rb +2 -2
  92. data/lib/action_view/helpers/tags/week_field.rb +2 -2
  93. data/lib/action_view/helpers/text_helper.rb +8 -5
  94. data/lib/action_view/helpers/url_helper.rb +18 -6
  95. data/lib/action_view/lookup_context.rb +7 -1
  96. data/lib/action_view/path_set.rb +6 -0
  97. data/lib/action_view/renderer/abstract_renderer.rb +15 -0
  98. data/lib/action_view/renderer/partial_renderer.rb +14 -0
  99. data/lib/action_view/renderer/renderer.rb +6 -0
  100. data/lib/action_view/template.rb +3 -2
  101. data/lib/action_view/template/handlers/erb.rb +29 -3
  102. data/lib/action_view/template/resolver.rb +3 -3
  103. data/lib/action_view/test_case.rb +1 -0
  104. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +5 -5
  105. data/lib/action_view/vendor/html-scanner/html/selector.rb +8 -8
  106. metadata +8 -8
@@ -94,7 +94,6 @@ module ActionController
94
94
  extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
95
95
  names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
96
96
  names.sort!
97
- names
98
97
  end
99
98
  helpers.uniq!
100
99
  helpers
@@ -27,7 +27,7 @@ module ActionController
27
27
  end
28
28
 
29
29
  def visible_action?(action_name)
30
- action_methods.include?(action_name)
30
+ not hidden_actions.include?(action_name)
31
31
  end
32
32
 
33
33
  # Overrides AbstractController::Base#action_methods to remove any methods
@@ -29,7 +29,7 @@ module ActionController
29
29
  #
30
30
  # protected
31
31
  # def set_account
32
- # @account = Account.find_by_url_name(request.subdomains.first)
32
+ # @account = Account.find_by(url_name: request.subdomains.first)
33
33
  # end
34
34
  #
35
35
  # def authenticate
@@ -299,6 +299,7 @@ module ActionController
299
299
  # allow a user to use new nonce without prompting user again for their
300
300
  # username and password.
301
301
  def validate_nonce(secret_key, request, value, seconds_to_timeout=5*60)
302
+ return false if value.nil?
302
303
  t = ::Base64.decode64(value).split(":").first.to_i
303
304
  nonce(secret_key, t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
304
305
  end
@@ -344,7 +345,7 @@ module ActionController
344
345
  #
345
346
  # protected
346
347
  # def set_account
347
- # @account = Account.find_by_url_name(request.subdomains.first)
348
+ # @account = Account.find_by(url_name: request.subdomains.first)
348
349
  # end
349
350
  #
350
351
  # def authenticate
@@ -14,6 +14,7 @@ module ActionController
14
14
  # response.stream.write "hello world\n"
15
15
  # sleep 1
16
16
  # }
17
+ # ensure
17
18
  # response.stream.close
18
19
  # end
19
20
  # end
@@ -33,6 +34,7 @@ module ActionController
33
34
  module Live
34
35
  class Buffer < ActionDispatch::Response::Buffer #:nodoc:
35
36
  def initialize(response)
37
+ @error_callback = nil
36
38
  super(response, SizedQueue.new(10))
37
39
  end
38
40
 
@@ -55,6 +57,14 @@ module ActionController
55
57
  super
56
58
  @buf.push nil
57
59
  end
60
+
61
+ def on_error(&block)
62
+ @error_callback = block
63
+ end
64
+
65
+ def call_on_error
66
+ @error_callback.call
67
+ end
58
68
  end
59
69
 
60
70
  class Response < ActionDispatch::Response #:nodoc: all
@@ -97,6 +107,10 @@ module ActionController
97
107
  def merge_default_headers(original, default)
98
108
  Header.new self, super
99
109
  end
110
+
111
+ def handle_conditional_get!
112
+ super unless committed?
113
+ end
100
114
  end
101
115
 
102
116
  def process(name)
@@ -116,6 +130,16 @@ module ActionController
116
130
 
117
131
  begin
118
132
  super(name)
133
+ rescue => e
134
+ begin
135
+ @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
136
+ @_response.stream.call_on_error
137
+ rescue => exception
138
+ log_error(exception)
139
+ ensure
140
+ log_error(e)
141
+ @_response.stream.close
142
+ end
119
143
  ensure
120
144
  @_response.commit!
121
145
  end
@@ -124,6 +148,16 @@ module ActionController
124
148
  @_response.await_commit
125
149
  end
126
150
 
151
+ def log_error(exception)
152
+ logger = ActionController::Base.logger
153
+ return unless logger
154
+
155
+ message = "\n#{exception.class} (#{exception.message}):\n"
156
+ message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
157
+ message << " " << exception.backtrace.join("\n ")
158
+ logger.fatal("#{message}\n\n")
159
+ end
160
+
127
161
  def response_body=(body)
128
162
  super
129
163
  response.stream.close if response
@@ -6,7 +6,7 @@ module ActionController
6
6
 
7
7
  # Before processing, set the request formats in current controller formats.
8
8
  def process_action(*) #:nodoc:
9
- self.formats = request.formats.map { |x| x.ref }
9
+ self.formats = request.formats.map(&:ref).compact
10
10
  super
11
11
  end
12
12
 
@@ -2,6 +2,7 @@ require 'active_support/core_ext/hash/indifferent_access'
2
2
  require 'active_support/core_ext/array/wrap'
3
3
  require 'active_support/rescuable'
4
4
  require 'action_dispatch/http/upload'
5
+ require 'stringio'
5
6
 
6
7
  module ActionController
7
8
  # Raised when a required parameter is missing.
@@ -68,6 +69,8 @@ module ActionController
68
69
  # ActionController::UnpermittedParameters exception. The default value is <tt>:log</tt>
69
70
  # in test and development environments, +false+ otherwise.
70
71
  #
72
+ # Examples:
73
+ #
71
74
  # params = ActionController::Parameters.new
72
75
  # params.permitted? # => false
73
76
  #
@@ -227,7 +230,7 @@ module ActionController
227
230
  # params = ActionController::Parameters.new({
228
231
  # person: {
229
232
  # contact: {
230
- # email: 'none@test.com'
233
+ # email: 'none@test.com',
231
234
  # phone: '555-1234'
232
235
  # }
233
236
  # }
@@ -339,7 +342,8 @@ module ActionController
339
342
  if unpermitted_keys.any?
340
343
  case self.class.action_on_unpermitted_parameters
341
344
  when :log
342
- ActionController::Base.logger.debug "Unpermitted parameters: #{unpermitted_keys.join(", ")}"
345
+ name = "unpermitted_parameters.action_controller"
346
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
343
347
  when :raise
344
348
  raise ActionController::UnpermittedParameters.new(unpermitted_keys)
345
349
  end
@@ -417,7 +421,7 @@ module ActionController
417
421
  # Declaration { comment_ids: [] }.
418
422
  array_of_permitted_scalars_filter(params, key)
419
423
  else
420
- # Declaration { user: :name } or { user: [:name, :age, { adress: ... }] }.
424
+ # Declaration { user: :name } or { user: [:name, :age, { address: ... }] }.
421
425
  params[key] = each_element(value) do |element|
422
426
  if element.is_a?(Hash)
423
427
  element = self.class.new(element) unless element.respond_to?(:permit)
@@ -16,8 +16,9 @@ module ActionController
16
16
  @_partials = Hash.new(0)
17
17
  @_templates = Hash.new(0)
18
18
  @_layouts = Hash.new(0)
19
+ @_files = Hash.new(0)
19
20
 
20
- ActiveSupport::Notifications.subscribe("render_template.action_view") do |name, start, finish, id, payload|
21
+ ActiveSupport::Notifications.subscribe("render_template.action_view") do |_name, _start, _finish, _id, payload|
21
22
  path = payload[:layout]
22
23
  if path
23
24
  @_layouts[path] += 1
@@ -27,7 +28,7 @@ module ActionController
27
28
  end
28
29
  end
29
30
 
30
- ActiveSupport::Notifications.subscribe("!render_template.action_view") do |name, start, finish, id, payload|
31
+ ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
31
32
  path = payload[:virtual_path]
32
33
  next unless path
33
34
  partial = path =~ /^.*\/_[^\/]*$/
@@ -39,6 +40,16 @@ module ActionController
39
40
 
40
41
  @_templates[path] += 1
41
42
  end
43
+
44
+ ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
45
+ next if payload[:virtual_path] # files don't have virtual path
46
+
47
+ path = payload[:identifier]
48
+ if path
49
+ @_files[path] += 1
50
+ @_files[path.split("/").last] += 1
51
+ end
52
+ end
42
53
  end
43
54
 
44
55
  def teardown_subscriptions
@@ -106,7 +117,7 @@ module ActionController
106
117
  end
107
118
  assert matches_template, msg
108
119
  when Hash
109
- options.assert_valid_keys(:layout, :partial, :locals, :count)
120
+ options.assert_valid_keys(:layout, :partial, :locals, :count, :file)
110
121
 
111
122
  if options.key?(:layout)
112
123
  expected_layout = options[:layout]
@@ -123,6 +134,10 @@ module ActionController
123
134
  end
124
135
  end
125
136
 
137
+ if options[:file]
138
+ assert_includes @_files.keys, options[:file]
139
+ end
140
+
126
141
  if expected_partial = options[:partial]
127
142
  if expected_locals = options[:locals]
128
143
  if defined?(@_rendered_views)
@@ -301,7 +316,7 @@ module ActionController
301
316
  # assert_response :found
302
317
  #
303
318
  # # Assert that the controller really put the book in the database.
304
- # assert_not_nil Book.find_by_title("Love Hina")
319
+ # assert_not_nil Book.find_by(title: "Love Hina")
305
320
  # end
306
321
  # end
307
322
  #
@@ -436,37 +451,56 @@ module ActionController
436
451
 
437
452
  end
438
453
 
439
- # Executes a request simulating GET HTTP method and set/volley the response
454
+ # Simulate a GET request with the given parameters.
455
+ #
456
+ # - +action+: The controller action to call.
457
+ # - +parameters+: The HTTP parameters that you want to pass. This may
458
+ # be +nil+, a hash, or a string that is appropriately encoded
459
+ # (<tt>application/x-www-form-urlencoded</tt> or <tt>multipart/form-data</tt>).
460
+ # - +session+: A hash of parameters to store in the session. This may be +nil+.
461
+ # - +flash+: A hash of parameters to store in the flash. This may be +nil+.
462
+ #
463
+ # You can also simulate POST, PATCH, PUT, DELETE, HEAD, and OPTIONS requests with
464
+ # +post+, +patch+, +put+, +delete+, +head+, and +options+.
465
+ #
466
+ # Note that the request method is not verified. The different methods are
467
+ # available to make the tests more expressive.
440
468
  def get(action, *args)
441
469
  process(action, "GET", *args)
442
470
  end
443
471
 
444
- # Executes a request simulating POST HTTP method and set/volley the response
472
+ # Simulate a POST request with the given parameters and set/volley the response.
473
+ # See +get+ for more details.
445
474
  def post(action, *args)
446
475
  process(action, "POST", *args)
447
476
  end
448
477
 
449
- # Executes a request simulating PATCH HTTP method and set/volley the response
478
+ # Simulate a PATCH request with the given parameters and set/volley the response.
479
+ # See +get+ for more details.
450
480
  def patch(action, *args)
451
481
  process(action, "PATCH", *args)
452
482
  end
453
483
 
454
- # Executes a request simulating PUT HTTP method and set/volley the response
484
+ # Simulate a PUT request with the given parameters and set/volley the response.
485
+ # See +get+ for more details.
455
486
  def put(action, *args)
456
487
  process(action, "PUT", *args)
457
488
  end
458
489
 
459
- # Executes a request simulating DELETE HTTP method and set/volley the response
490
+ # Simulate a DELETE request with the given parameters and set/volley the response.
491
+ # See +get+ for more details.
460
492
  def delete(action, *args)
461
493
  process(action, "DELETE", *args)
462
494
  end
463
495
 
464
- # Executes a request simulating HEAD HTTP method and set/volley the response
496
+ # Simulate a HEAD request with the given parameters and set/volley the response.
497
+ # See +get+ for more details.
465
498
  def head(action, *args)
466
499
  process(action, "HEAD", *args)
467
500
  end
468
501
 
469
- # Executes a request simulating OPTIONS HTTP method and set/volley the response
502
+ # Simulate a OPTIONS request with the given parameters and set/volley the response.
503
+ # See +get+ for more details.
470
504
  def options(action, *args)
471
505
  process(action, "OPTIONS", *args)
472
506
  end
@@ -82,12 +82,10 @@ module ActionDispatch
82
82
  end
83
83
 
84
84
  module Session
85
- autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store'
86
- autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store'
87
- autoload :EncryptedCookieStore, 'action_dispatch/middleware/session/cookie_store'
88
- autoload :UpgradeSignatureToEncryptionCookieStore, 'action_dispatch/middleware/session/cookie_store'
89
- autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store'
90
- autoload :CacheStore, 'action_dispatch/middleware/session/cache_store'
85
+ autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store'
86
+ autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store'
87
+ autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store'
88
+ autoload :CacheStore, 'action_dispatch/middleware/session/cache_store'
91
89
  end
92
90
 
93
91
  mattr_accessor :test_app
@@ -92,7 +92,7 @@ module ActionDispatch
92
92
  LAST_MODIFIED = "Last-Modified".freeze
93
93
  ETAG = "ETag".freeze
94
94
  CACHE_CONTROL = "Cache-Control".freeze
95
- SPESHUL_KEYS = %w[extras no-cache max-age public must-revalidate]
95
+ SPECIAL_KEYS = %w[extras no-cache max-age public must-revalidate]
96
96
 
97
97
  def cache_control_segments
98
98
  if cache_control = self[CACHE_CONTROL]
@@ -108,7 +108,7 @@ module ActionDispatch
108
108
  cache_control_segments.each do |segment|
109
109
  directive, argument = segment.split('=', 2)
110
110
 
111
- if SPESHUL_KEYS.include? directive
111
+ if SPECIAL_KEYS.include? directive
112
112
  key = directive.tr('-', '_')
113
113
  cache_control[key.to_sym] = argument || true
114
114
  else
@@ -1,38 +1,62 @@
1
1
  module ActionDispatch
2
2
  module Http
3
3
  class Headers
4
+ CGI_VARIABLES = %w(
5
+ CONTENT_TYPE CONTENT_LENGTH
6
+ HTTPS AUTH_TYPE GATEWAY_INTERFACE
7
+ PATH_INFO PATH_TRANSLATED QUERY_STRING
8
+ REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER
9
+ REQUEST_METHOD SCRIPT_NAME
10
+ SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE
11
+ )
12
+ HTTP_HEADER = /\A[A-Za-z0-9-]+\z/
13
+
4
14
  include Enumerable
15
+ attr_reader :env
5
16
 
6
17
  def initialize(env = {})
7
- @headers = env
18
+ @env = env
19
+ end
20
+
21
+ def [](key)
22
+ @env[env_name(key)]
8
23
  end
9
24
 
10
- def [](header_name)
11
- @headers[env_name(header_name)]
25
+ def []=(key, value)
26
+ @env[env_name(key)] = value
12
27
  end
13
28
 
14
- def []=(k,v); @headers[k] = v; end
15
- def key?(k); @headers.key? k; end
29
+ def key?(key); @env.key? key; end
16
30
  alias :include? :key?
17
31
 
18
- def fetch(header_name, *args, &block)
19
- @headers.fetch env_name(header_name), *args, &block
32
+ def fetch(key, *args, &block)
33
+ @env.fetch env_name(key), *args, &block
20
34
  end
21
35
 
22
36
  def each(&block)
23
- @headers.each(&block)
37
+ @env.each(&block)
24
38
  end
25
39
 
26
- private
40
+ def merge(headers_or_env)
41
+ headers = Http::Headers.new(env.dup)
42
+ headers.merge!(headers_or_env)
43
+ headers
44
+ end
27
45
 
28
- # Converts a HTTP header name to an environment variable name if it is
29
- # not contained within the headers hash.
30
- def env_name(header_name)
31
- @headers.include?(header_name) ? header_name : cgi_name(header_name)
46
+ def merge!(headers_or_env)
47
+ headers_or_env.each do |key, value|
48
+ self[env_name(key)] = value
49
+ end
32
50
  end
33
51
 
34
- def cgi_name(k)
35
- "HTTP_#{k.upcase.gsub(/-/, '_')}"
52
+ private
53
+ def env_name(key)
54
+ key = key.to_s
55
+ if key =~ HTTP_HEADER
56
+ key = key.upcase.tr('-', '_')
57
+ key = "HTTP_" + key unless CGI_VARIABLES.include?(key)
58
+ end
59
+ key
36
60
  end
37
61
  end
38
62
  end
@@ -121,7 +121,7 @@ module ActionDispatch
121
121
  BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
122
122
 
123
123
  def valid_accept_header
124
- (xhr? && (accept || content_mime_type)) ||
124
+ (xhr? && (accept.present? || content_mime_type)) ||
125
125
  (accept.present? && accept !~ BROWSER_LIKE_ACCEPTS)
126
126
  end
127
127
 
@@ -223,8 +223,8 @@ module Mime
223
223
  Mime.instance_eval { remove_const(symbol) }
224
224
 
225
225
  SET.delete_if { |v| v.eql?(mime) }
226
- LOOKUP.delete_if { |k,v| v.eql?(mime) }
227
- EXTENSION_LOOKUP.delete_if { |k,v| v.eql?(mime) }
226
+ LOOKUP.delete_if { |_,v| v.eql?(mime) }
227
+ EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
228
228
  end
229
229
  end
230
230
 
@@ -306,12 +306,20 @@ module Mime
306
306
  method.to_s.ends_with? '?'
307
307
  end
308
308
  end
309
-
309
+
310
310
  class NullType
311
311
  def nil?
312
312
  true
313
313
  end
314
314
 
315
+ def ref
316
+ nil
317
+ end
318
+
319
+ def respond_to_missing?(method, include_private = false)
320
+ method.to_s.ends_with? '?'
321
+ end
322
+
315
323
  private
316
324
  def method_missing(method, *args)
317
325
  false if method.to_s.ends_with? '?'