actionpack 4.2.10 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +553 -401
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/base.rb +28 -38
  6. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
  7. data/lib/abstract_controller/caching.rb +62 -0
  8. data/lib/abstract_controller/callbacks.rb +52 -19
  9. data/lib/abstract_controller/collector.rb +4 -9
  10. data/lib/abstract_controller/error.rb +4 -0
  11. data/lib/abstract_controller/helpers.rb +4 -3
  12. data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
  13. data/lib/abstract_controller/rendering.rb +28 -18
  14. data/lib/abstract_controller/translation.rb +8 -7
  15. data/lib/abstract_controller.rb +6 -2
  16. data/lib/action_controller/api/api_rendering.rb +14 -0
  17. data/lib/action_controller/api.rb +147 -0
  18. data/lib/action_controller/base.rb +10 -13
  19. data/lib/action_controller/caching.rb +13 -58
  20. data/lib/action_controller/form_builder.rb +48 -0
  21. data/lib/action_controller/log_subscriber.rb +3 -10
  22. data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
  23. data/lib/action_controller/metal/conditional_get.rb +106 -34
  24. data/lib/action_controller/metal/cookies.rb +1 -3
  25. data/lib/action_controller/metal/data_streaming.rb +11 -32
  26. data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
  27. data/lib/action_controller/metal/exceptions.rb +11 -6
  28. data/lib/action_controller/metal/force_ssl.rb +10 -10
  29. data/lib/action_controller/metal/head.rb +14 -8
  30. data/lib/action_controller/metal/helpers.rb +15 -6
  31. data/lib/action_controller/metal/http_authentication.rb +44 -35
  32. data/lib/action_controller/metal/implicit_render.rb +61 -6
  33. data/lib/action_controller/metal/instrumentation.rb +5 -5
  34. data/lib/action_controller/metal/live.rb +66 -88
  35. data/lib/action_controller/metal/mime_responds.rb +27 -42
  36. data/lib/action_controller/metal/params_wrapper.rb +8 -8
  37. data/lib/action_controller/metal/redirecting.rb +32 -9
  38. data/lib/action_controller/metal/renderers.rb +85 -40
  39. data/lib/action_controller/metal/rendering.rb +38 -6
  40. data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
  41. data/lib/action_controller/metal/rescue.rb +3 -12
  42. data/lib/action_controller/metal/streaming.rb +4 -4
  43. data/lib/action_controller/metal/strong_parameters.rb +293 -90
  44. data/lib/action_controller/metal/testing.rb +1 -12
  45. data/lib/action_controller/metal/url_for.rb +12 -5
  46. data/lib/action_controller/metal.rb +88 -63
  47. data/lib/action_controller/renderer.rb +111 -0
  48. data/lib/action_controller/template_assertions.rb +9 -0
  49. data/lib/action_controller/test_case.rb +288 -368
  50. data/lib/action_controller.rb +12 -9
  51. data/lib/action_dispatch/http/cache.rb +73 -34
  52. data/lib/action_dispatch/http/filter_parameters.rb +15 -11
  53. data/lib/action_dispatch/http/filter_redirect.rb +7 -8
  54. data/lib/action_dispatch/http/headers.rb +44 -13
  55. data/lib/action_dispatch/http/mime_negotiation.rb +41 -23
  56. data/lib/action_dispatch/http/mime_type.rb +126 -90
  57. data/lib/action_dispatch/http/mime_types.rb +3 -4
  58. data/lib/action_dispatch/http/parameter_filter.rb +18 -8
  59. data/lib/action_dispatch/http/parameters.rb +54 -41
  60. data/lib/action_dispatch/http/request.rb +149 -82
  61. data/lib/action_dispatch/http/response.rb +206 -102
  62. data/lib/action_dispatch/http/url.rb +117 -8
  63. data/lib/action_dispatch/journey/formatter.rb +39 -28
  64. data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
  65. data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
  66. data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
  67. data/lib/action_dispatch/journey/nodes/node.rb +14 -4
  68. data/lib/action_dispatch/journey/parser_extras.rb +4 -0
  69. data/lib/action_dispatch/journey/path/pattern.rb +38 -42
  70. data/lib/action_dispatch/journey/route.rb +74 -19
  71. data/lib/action_dispatch/journey/router/utils.rb +5 -5
  72. data/lib/action_dispatch/journey/router.rb +5 -9
  73. data/lib/action_dispatch/journey/routes.rb +14 -15
  74. data/lib/action_dispatch/journey/visitors.rb +86 -43
  75. data/lib/action_dispatch/middleware/callbacks.rb +10 -1
  76. data/lib/action_dispatch/middleware/cookies.rb +189 -135
  77. data/lib/action_dispatch/middleware/debug_exceptions.rb +124 -49
  78. data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
  79. data/lib/action_dispatch/middleware/executor.rb +19 -0
  80. data/lib/action_dispatch/middleware/flash.rb +66 -45
  81. data/lib/action_dispatch/middleware/params_parser.rb +32 -46
  82. data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
  83. data/lib/action_dispatch/middleware/reloader.rb +14 -58
  84. data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
  85. data/lib/action_dispatch/middleware/request_id.rb +11 -6
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
  89. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
  90. data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
  91. data/lib/action_dispatch/middleware/ssl.rb +115 -36
  92. data/lib/action_dispatch/middleware/stack.rb +44 -40
  93. data/lib/action_dispatch/middleware/static.rb +51 -35
  94. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
  95. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  96. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
  97. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  98. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  99. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
  100. data/lib/action_dispatch/railtie.rb +2 -2
  101. data/lib/action_dispatch/request/session.rb +69 -33
  102. data/lib/action_dispatch/request/utils.rb +51 -19
  103. data/lib/action_dispatch/routing/inspector.rb +32 -43
  104. data/lib/action_dispatch/routing/mapper.rb +491 -338
  105. data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
  106. data/lib/action_dispatch/routing/redirection.rb +3 -3
  107. data/lib/action_dispatch/routing/route_set.rb +145 -238
  108. data/lib/action_dispatch/routing/url_for.rb +27 -10
  109. data/lib/action_dispatch/routing.rb +17 -13
  110. data/lib/action_dispatch/testing/assertion_response.rb +45 -0
  111. data/lib/action_dispatch/testing/assertions/response.rb +38 -20
  112. data/lib/action_dispatch/testing/assertions/routing.rb +11 -10
  113. data/lib/action_dispatch/testing/assertions.rb +1 -1
  114. data/lib/action_dispatch/testing/integration.rb +368 -97
  115. data/lib/action_dispatch/testing/test_process.rb +5 -6
  116. data/lib/action_dispatch/testing/test_request.rb +22 -31
  117. data/lib/action_dispatch/testing/test_response.rb +7 -4
  118. data/lib/action_dispatch.rb +3 -1
  119. data/lib/action_pack/gem_version.rb +3 -3
  120. data/lib/action_pack.rb +1 -1
  121. metadata +30 -34
  122. data/lib/action_controller/metal/hide_actions.rb +0 -40
  123. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  124. data/lib/action_controller/middleware.rb +0 -39
  125. data/lib/action_controller/model_naming.rb +0 -12
  126. data/lib/action_dispatch/journey/backwards.rb +0 -5
  127. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  128. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  129. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  130. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
  131. /data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
@@ -1,5 +1,7 @@
1
1
  require 'active_support/core_ext/array/extract_options'
2
2
  require 'action_dispatch/middleware/stack'
3
+ require 'action_dispatch/http/request'
4
+ require 'action_dispatch/http/response'
3
5
 
4
6
  module ActionController
5
7
  # Extend ActionDispatch middleware stack to make it aware of options
@@ -11,22 +13,14 @@ module ActionController
11
13
  #
12
14
  class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc:
13
15
  class Middleware < ActionDispatch::MiddlewareStack::Middleware #:nodoc:
14
- def initialize(klass, *args, &block)
15
- options = args.extract_options!
16
- @only = Array(options.delete(:only)).map(&:to_s)
17
- @except = Array(options.delete(:except)).map(&:to_s)
18
- args << options unless options.empty?
19
- super
16
+ def initialize(klass, args, actions, strategy, block)
17
+ @actions = actions
18
+ @strategy = strategy
19
+ super(klass, args, block)
20
20
  end
21
21
 
22
22
  def valid?(action)
23
- if @only.present?
24
- @only.include?(action)
25
- elsif @except.present?
26
- !@except.include?(action)
27
- else
28
- true
29
- end
23
+ @strategy.call @actions, action
30
24
  end
31
25
  end
32
26
 
@@ -37,6 +31,32 @@ module ActionController
37
31
  middleware.valid?(action) ? middleware.build(a) : a
38
32
  end
39
33
  end
34
+
35
+ private
36
+
37
+ INCLUDE = ->(list, action) { list.include? action }
38
+ EXCLUDE = ->(list, action) { !list.include? action }
39
+ NULL = ->(list, action) { true }
40
+
41
+ def build_middleware(klass, args, block)
42
+ options = args.extract_options!
43
+ only = Array(options.delete(:only)).map(&:to_s)
44
+ except = Array(options.delete(:except)).map(&:to_s)
45
+ args << options unless options.empty?
46
+
47
+ strategy = NULL
48
+ list = nil
49
+
50
+ if only.any?
51
+ strategy = INCLUDE
52
+ list = only
53
+ elsif except.any?
54
+ strategy = EXCLUDE
55
+ list = except
56
+ end
57
+
58
+ Middleware.new(get_class(klass), args, list, strategy, block)
59
+ end
40
60
  end
41
61
 
42
62
  # <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
@@ -98,11 +118,10 @@ module ActionController
98
118
  class Metal < AbstractController::Base
99
119
  abstract!
100
120
 
101
- attr_internal_writer :env
102
-
103
121
  def env
104
- @_env ||= {}
122
+ @_request.env
105
123
  end
124
+ deprecate :env
106
125
 
107
126
  # Returns the last part of the controller's name, underscored, without the ending
108
127
  # <tt>Controller</tt>. For instance, PostsController returns <tt>posts</tt>.
@@ -114,23 +133,23 @@ module ActionController
114
133
  @controller_name ||= name.demodulize.sub(/Controller$/, '').underscore
115
134
  end
116
135
 
136
+ def self.make_response!(request)
137
+ ActionDispatch::Response.create.tap do |res|
138
+ res.request = request
139
+ end
140
+ end
141
+
117
142
  # Delegates to the class' <tt>controller_name</tt>
118
143
  def controller_name
119
144
  self.class.controller_name
120
145
  end
121
146
 
122
- # The details below can be overridden to support a specific
123
- # Request and Response object. The default ActionController::Base
124
- # implementation includes RackDelegation, which makes a request
125
- # and response object available. You might wish to control the
126
- # environment and response manually for performance reasons.
127
-
128
- attr_internal :headers, :response, :request
147
+ attr_internal :response, :request
129
148
  delegate :session, :to => "@_request"
149
+ delegate :headers, :status=, :location=, :content_type=,
150
+ :status, :location, :content_type, :to => "@_response"
130
151
 
131
152
  def initialize
132
- @_headers = {"Content-Type" => "text/html"}
133
- @_status = 200
134
153
  @_request = nil
135
154
  @_response = nil
136
155
  @_routes = nil
@@ -145,60 +164,49 @@ module ActionController
145
164
  @_params = val
146
165
  end
147
166
 
148
- # Basic implementations for content_type=, location=, and headers are
149
- # provided to reduce the dependency on the RackDelegation module
150
- # in Renderer and Redirector.
151
-
152
- def content_type=(type)
153
- headers["Content-Type"] = type.to_s
154
- end
155
-
156
- def content_type
157
- headers["Content-Type"]
158
- end
159
-
160
- def location
161
- headers["Location"]
162
- end
163
-
164
- def location=(url)
165
- headers["Location"] = url
166
- end
167
+ alias :response_code :status # :nodoc:
167
168
 
168
- # Basic url_for that can be overridden for more robust functionality
169
+ # Basic url_for that can be overridden for more robust functionality.
169
170
  def url_for(string)
170
171
  string
171
172
  end
172
173
 
173
- def status
174
- @_status
175
- end
176
- alias :response_code :status # :nodoc:
177
-
178
- def status=(status)
179
- @_status = Rack::Utils.status_code(status)
180
- end
181
-
182
174
  def response_body=(body)
183
175
  body = [body] unless body.nil? || body.respond_to?(:each)
176
+ response.reset_body!
177
+ return unless body
178
+ response.body = body
184
179
  super
185
180
  end
186
181
 
187
182
  # Tests if render or redirect has already happened.
188
183
  def performed?
189
- response_body || (response && response.committed?)
184
+ response_body || response.committed?
190
185
  end
191
186
 
192
- def dispatch(name, request) #:nodoc:
193
- @_request = request
194
- @_env = request.env
195
- @_env['action_controller.instance'] = self
187
+ def dispatch(name, request, response) #:nodoc:
188
+ set_request!(request)
189
+ set_response!(response)
196
190
  process(name)
191
+ request.commit_flash
197
192
  to_a
198
193
  end
199
194
 
195
+ def set_response!(response) # :nodoc:
196
+ @_response = response
197
+ end
198
+
199
+ def set_request!(request) #:nodoc:
200
+ @_request = request
201
+ @_request.controller_instance = self
202
+ end
203
+
200
204
  def to_a #:nodoc:
201
- response ? response.to_a : [status, headers, response_body]
205
+ response.to_a
206
+ end
207
+
208
+ def reset_session
209
+ @_request.reset_session
202
210
  end
203
211
 
204
212
  class_attribute :middleware_stack
@@ -226,15 +234,32 @@ module ActionController
226
234
  req = ActionDispatch::Request.new env
227
235
  action(req.path_parameters[:action]).call(env)
228
236
  end
237
+ class << self; deprecate :call; end
229
238
 
230
239
  # Returns a Rack endpoint for the given action name.
231
- def self.action(name, klass = ActionDispatch::Request)
240
+ def self.action(name)
232
241
  if middleware_stack.any?
233
242
  middleware_stack.build(name) do |env|
234
- new.dispatch(name, klass.new(env))
243
+ req = ActionDispatch::Request.new(env)
244
+ res = make_response! req
245
+ new.dispatch(name, req, res)
235
246
  end
236
247
  else
237
- lambda { |env| new.dispatch(name, klass.new(env)) }
248
+ lambda { |env|
249
+ req = ActionDispatch::Request.new(env)
250
+ res = make_response! req
251
+ new.dispatch(name, req, res)
252
+ }
253
+ end
254
+ end
255
+
256
+ # Direct dispatch to the controller. Instantiates the controller, then
257
+ # executes the action named +name+.
258
+ def self.dispatch(name, req, res)
259
+ if middleware_stack.any?
260
+ middleware_stack.build(name) { |env| new.dispatch(name, req, res) }.call req.env
261
+ else
262
+ new.dispatch(name, req, res)
238
263
  end
239
264
  end
240
265
  end
@@ -0,0 +1,111 @@
1
+ require 'active_support/core_ext/hash/keys'
2
+
3
+ module ActionController
4
+ # ActionController::Renderer allows to render arbitrary templates
5
+ # without requirement of being in controller actions.
6
+ #
7
+ # You get a concrete renderer class by invoking ActionController::Base#renderer.
8
+ # For example,
9
+ #
10
+ # ApplicationController.renderer
11
+ #
12
+ # It allows you to call method #render directly.
13
+ #
14
+ # ApplicationController.renderer.render template: '...'
15
+ #
16
+ # You can use this shortcut in a controller, instead of the previous example:
17
+ #
18
+ # ApplicationController.render template: '...'
19
+ #
20
+ # #render allows you to use the same options that you can use when rendering in a controller.
21
+ # For example,
22
+ #
23
+ # FooController.render :action, locals: { ... }, assigns: { ... }
24
+ #
25
+ # The template will be rendered in a Rack environment which is accessible through
26
+ # ActionController::Renderer#env. You can set it up in two ways:
27
+ #
28
+ # * by changing renderer defaults, like
29
+ #
30
+ # ApplicationController.renderer.defaults # => hash with default Rack environment
31
+ #
32
+ # * by initializing an instance of renderer by passing it a custom environment.
33
+ #
34
+ # ApplicationController.renderer.new(method: 'post', https: true)
35
+ #
36
+ class Renderer
37
+ attr_reader :defaults, :controller
38
+
39
+ DEFAULTS = {
40
+ http_host: 'example.org',
41
+ https: false,
42
+ method: 'get',
43
+ script_name: '',
44
+ input: ''
45
+ }.freeze
46
+
47
+ # Create a new renderer instance for a specific controller class.
48
+ def self.for(controller, env = {}, defaults = DEFAULTS.dup)
49
+ new(controller, env, defaults)
50
+ end
51
+
52
+ # Create a new renderer for the same controller but with a new env.
53
+ def new(env = {})
54
+ self.class.new controller, env, defaults
55
+ end
56
+
57
+ # Create a new renderer for the same controller but with new defaults.
58
+ def with_defaults(defaults)
59
+ self.class.new controller, env, self.defaults.merge(defaults)
60
+ end
61
+
62
+ # Accepts a custom Rack environment to render templates in.
63
+ # It will be merged with ActionController::Renderer.defaults
64
+ def initialize(controller, env, defaults)
65
+ @controller = controller
66
+ @defaults = defaults
67
+ @env = normalize_keys defaults.merge(env)
68
+ end
69
+
70
+ # Render templates with any options from ActionController::Base#render_to_string.
71
+ def render(*args)
72
+ raise 'missing controller' unless controller
73
+
74
+ request = ActionDispatch::Request.new @env
75
+ request.routes = controller._routes
76
+
77
+ instance = controller.new
78
+ instance.set_request! request
79
+ instance.set_response! controller.make_response!(request)
80
+ instance.render_to_string(*args)
81
+ end
82
+
83
+ private
84
+ def normalize_keys(env)
85
+ new_env = {}
86
+ env.each_pair { |k,v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
87
+ new_env
88
+ end
89
+
90
+ RACK_KEY_TRANSLATION = {
91
+ http_host: 'HTTP_HOST',
92
+ https: 'HTTPS',
93
+ method: 'REQUEST_METHOD',
94
+ script_name: 'SCRIPT_NAME',
95
+ input: 'rack.input'
96
+ }
97
+
98
+ IDENTITY = ->(_) { _ }
99
+
100
+ RACK_VALUE_TRANSLATION = {
101
+ https: ->(v) { v ? 'on' : 'off' },
102
+ method: ->(v) { v.upcase },
103
+ }
104
+
105
+ def rack_key_for(key); RACK_KEY_TRANSLATION[key]; end
106
+
107
+ def rack_value_for(key, value)
108
+ RACK_VALUE_TRANSLATION.fetch(key, IDENTITY).call value
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,9 @@
1
+ module ActionController
2
+ module TemplateAssertions
3
+ def assert_template(options = {}, message = nil)
4
+ raise NoMethodError,
5
+ "assert_template has been extracted to a gem. To continue using it,
6
+ add `gem 'rails-controller-testing'` to your Gemfile."
7
+ end
8
+ end
9
+ end