actionpack 4.1.0.rc1 → 4.1.0.rc2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -8
- data/README.rdoc +1 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +6 -6
- data/lib/action_controller/metal/live.rb +42 -16
- data/lib/action_controller/metal/rack_delegation.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +1 -3
- data/lib/action_controller/metal/testing.rb +0 -1
- data/lib/action_controller/test_case.rb +38 -7
- data/lib/action_dispatch.rb +0 -1
- data/lib/action_dispatch/http/response.rb +35 -15
- data/lib/action_dispatch/middleware/cookies.rb +16 -5
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +42 -31
- data/lib/action_dispatch/testing/assertions/selector.rb +1 -1
- data/lib/action_pack/gem_version.rb +15 -0
- data/lib/action_pack/version.rb +4 -7
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6c555c15afe7bbf436b5da70ea45df0d4fc6578
|
4
|
+
data.tar.gz: 5940cf368c174b4c945db943b07867baafea367c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 722e8d0402501afcbbd87de1ee7d1e0da5460e4cad57dbd6b02713612ae73ea317f3479c8b31f56ed62ef6dfeb3b48c01d363138d0d912074f3630a973f67066
|
7
|
+
data.tar.gz: 6c87df659e5dd0ebd123d37f0f53bc6f3a48d147b1bcd779c35b86475df6a6342b7346fdd1e3ccba104426b998ea1d6199e246c0fb43ea9afed6b945f9b16a8c
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
+
* Swapped the parameters of assert_equal in `assert_select` so that the
|
2
|
+
proper values were printed correctly
|
3
|
+
|
4
|
+
Fixes #14422.
|
5
|
+
|
6
|
+
*Vishal Lal*
|
7
|
+
|
8
|
+
* Fix URL generation in controller tests with request-dependent
|
9
|
+
`default_url_options` methods.
|
10
|
+
|
11
|
+
*Tony Wooster*
|
12
|
+
|
1
13
|
* Introduce `render :html` as an option to render HTML content with a content
|
2
14
|
type of `text/html`. This rendering option calls `ERB::Util.html_escape`
|
3
15
|
internally to escape unsafe HTML string, so you will have to mark your
|
4
16
|
string as html safe if you have any HTML tag in it.
|
5
17
|
|
6
|
-
|
18
|
+
See #14062, #12374.
|
7
19
|
|
8
20
|
*Prem Sichanugrist*
|
9
21
|
|
@@ -11,19 +23,19 @@
|
|
11
23
|
of `text/plain`. This is the preferred option if you are planning to render
|
12
24
|
a plain text content.
|
13
25
|
|
14
|
-
|
26
|
+
See #14062, #12374.
|
15
27
|
|
16
28
|
*Prem Sichanugrist*
|
17
29
|
|
18
30
|
* Introduce `render :body` as an option for sending a raw content back to
|
19
|
-
browser. Note that this rendering option
|
20
|
-
|
31
|
+
browser. Note that this rendering option does not include "Content-Type"
|
32
|
+
header back in the response.
|
21
33
|
|
22
|
-
You should only use this option if you
|
23
|
-
|
34
|
+
You should only use this option if you don't care about the content type
|
35
|
+
of the response. More information on "Content-Type" header can be found
|
24
36
|
on RFC 2616, section 7.2.1.
|
25
37
|
|
26
|
-
|
38
|
+
See #14062, #12374.
|
27
39
|
|
28
40
|
*Prem Sichanugrist*
|
29
41
|
|
@@ -117,7 +129,7 @@
|
|
117
129
|
|
118
130
|
* Fix stream closing when sending file with `ActionController::Live` included.
|
119
131
|
|
120
|
-
Fixes #12381
|
132
|
+
Fixes #12381.
|
121
133
|
|
122
134
|
*Alessandro Diaferia*
|
123
135
|
|
data/README.rdoc
CHANGED
@@ -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/
|
35
|
+
* https://github.com/rails/rails/tree/4-1-stable/actionpack
|
36
36
|
|
37
37
|
|
38
38
|
== License
|
@@ -54,9 +54,9 @@ module ActionController
|
|
54
54
|
end
|
55
55
|
|
56
56
|
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"\
|
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
60
|
"for more information."\
|
61
61
|
|
62
62
|
debug(message)
|
@@ -96,7 +96,7 @@ module ActionController #:nodoc:
|
|
96
96
|
end
|
97
97
|
|
98
98
|
# Sends the given binary data to the browser. This method is similar to
|
99
|
-
# <tt>render
|
99
|
+
# <tt>render plain: data</tt>, but also allows you to specify whether
|
100
100
|
# the browser should display the response as a file attachment (i.e. in a
|
101
101
|
# download dialog) or as inline data. You may also set the content type,
|
102
102
|
# the apparent file name, and other things.
|
@@ -11,11 +11,11 @@ module ActionController
|
|
11
11
|
# http_basic_authenticate_with name: "dhh", password: "secret", except: :index
|
12
12
|
#
|
13
13
|
# def index
|
14
|
-
# render
|
14
|
+
# render plain: "Everyone can see me!"
|
15
15
|
# end
|
16
16
|
#
|
17
17
|
# def edit
|
18
|
-
# render
|
18
|
+
# render plain: "I'm only accessible if you know the password"
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
#
|
@@ -127,11 +127,11 @@ module ActionController
|
|
127
127
|
# before_action :authenticate, except: [:index]
|
128
128
|
#
|
129
129
|
# def index
|
130
|
-
# render
|
130
|
+
# render plain: "Everyone can see me!"
|
131
131
|
# end
|
132
132
|
#
|
133
133
|
# def edit
|
134
|
-
# render
|
134
|
+
# render plain: "I'm only accessible if you know the password"
|
135
135
|
# end
|
136
136
|
#
|
137
137
|
# private
|
@@ -321,11 +321,11 @@ module ActionController
|
|
321
321
|
# before_action :authenticate, except: [ :index ]
|
322
322
|
#
|
323
323
|
# def index
|
324
|
-
# render
|
324
|
+
# render plain: "Everyone can see me!"
|
325
325
|
# end
|
326
326
|
#
|
327
327
|
# def edit
|
328
|
-
# render
|
328
|
+
# render plain: "I'm only accessible if you know the password"
|
329
329
|
# end
|
330
330
|
#
|
331
331
|
# private
|
@@ -107,8 +107,11 @@ module ActionController
|
|
107
107
|
end
|
108
108
|
|
109
109
|
class Buffer < ActionDispatch::Response::Buffer #:nodoc:
|
110
|
+
include MonitorMixin
|
111
|
+
|
110
112
|
def initialize(response)
|
111
|
-
@error_callback =
|
113
|
+
@error_callback = lambda { true }
|
114
|
+
@cv = new_cond
|
112
115
|
super(response, SizedQueue.new(10))
|
113
116
|
end
|
114
117
|
|
@@ -122,14 +125,25 @@ module ActionController
|
|
122
125
|
end
|
123
126
|
|
124
127
|
def each
|
128
|
+
@response.sending!
|
125
129
|
while str = @buf.pop
|
126
130
|
yield str
|
127
131
|
end
|
132
|
+
@response.sent!
|
128
133
|
end
|
129
134
|
|
130
135
|
def close
|
131
|
-
|
132
|
-
|
136
|
+
synchronize do
|
137
|
+
super
|
138
|
+
@buf.push nil
|
139
|
+
@cv.broadcast
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def await_close
|
144
|
+
synchronize do
|
145
|
+
@cv.wait_until { @closed }
|
146
|
+
end
|
133
147
|
end
|
134
148
|
|
135
149
|
def on_error(&block)
|
@@ -165,12 +179,20 @@ module ActionController
|
|
165
179
|
end
|
166
180
|
end
|
167
181
|
|
168
|
-
|
169
|
-
|
182
|
+
private
|
183
|
+
|
184
|
+
def before_committed
|
170
185
|
super
|
186
|
+
jar = request.cookie_jar
|
187
|
+
# The response can be committed multiple times
|
188
|
+
jar.write self unless committed?
|
171
189
|
end
|
172
190
|
|
173
|
-
|
191
|
+
def before_sending
|
192
|
+
super
|
193
|
+
request.cookie_jar.commit!
|
194
|
+
headers.freeze
|
195
|
+
end
|
174
196
|
|
175
197
|
def build_buffer(response, body)
|
176
198
|
buf = Live::Buffer.new response
|
@@ -191,6 +213,7 @@ module ActionController
|
|
191
213
|
t1 = Thread.current
|
192
214
|
locals = t1.keys.map { |key| [key, t1[key]] }
|
193
215
|
|
216
|
+
error = nil
|
194
217
|
# This processes the action in a child thread. It lets us return the
|
195
218
|
# response code and headers back up the rack stack, and still process
|
196
219
|
# the body in parallel with sending data to the client
|
@@ -205,16 +228,18 @@ module ActionController
|
|
205
228
|
begin
|
206
229
|
super(name)
|
207
230
|
rescue => e
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
231
|
+
if @_response.committed?
|
232
|
+
begin
|
233
|
+
@_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
|
234
|
+
@_response.stream.call_on_error
|
235
|
+
rescue => exception
|
236
|
+
log_error(exception)
|
237
|
+
ensure
|
238
|
+
log_error(e)
|
239
|
+
@_response.stream.close
|
240
|
+
end
|
241
|
+
else
|
242
|
+
error = e
|
218
243
|
end
|
219
244
|
ensure
|
220
245
|
@_response.commit!
|
@@ -222,6 +247,7 @@ module ActionController
|
|
222
247
|
}
|
223
248
|
|
224
249
|
@_response.await_commit
|
250
|
+
raise error if error
|
225
251
|
end
|
226
252
|
|
227
253
|
def log_error(exception)
|
@@ -5,8 +5,8 @@ module ActionController
|
|
5
5
|
module RackDelegation
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
-
delegate :headers, :status=, :location=, :content_type=,
|
9
|
-
:status, :location, :content_type, :
|
8
|
+
delegate :headers, :status=, :location=, :content_type=,
|
9
|
+
:status, :location, :content_type, :to => "@_response"
|
10
10
|
|
11
11
|
def dispatch(action, request)
|
12
12
|
set_response!(request)
|
@@ -45,9 +45,7 @@ module ActionController
|
|
45
45
|
def _process_format(format, options = {})
|
46
46
|
super
|
47
47
|
|
48
|
-
if options[:
|
49
|
-
self.headers.delete "Content-Type"
|
50
|
-
elsif options[:plain]
|
48
|
+
if options[:plain]
|
51
49
|
self.content_type = Mime::TEXT
|
52
50
|
else
|
53
51
|
self.content_type ||= format.to_s
|
@@ -258,6 +258,29 @@ module ActionController
|
|
258
258
|
end
|
259
259
|
end
|
260
260
|
|
261
|
+
class LiveTestResponse < Live::Response
|
262
|
+
def recycle!
|
263
|
+
@body = nil
|
264
|
+
initialize
|
265
|
+
end
|
266
|
+
|
267
|
+
def body
|
268
|
+
@body ||= super
|
269
|
+
end
|
270
|
+
|
271
|
+
# Was the response successful?
|
272
|
+
alias_method :success?, :successful?
|
273
|
+
|
274
|
+
# Was the URL not found?
|
275
|
+
alias_method :missing?, :not_found?
|
276
|
+
|
277
|
+
# Were we redirected?
|
278
|
+
alias_method :redirect?, :redirection?
|
279
|
+
|
280
|
+
# Was there a server-side error?
|
281
|
+
alias_method :error?, :server_error?
|
282
|
+
end
|
283
|
+
|
261
284
|
# Methods #destroy and #load! are overridden to avoid calling methods on the
|
262
285
|
# @store object, which does not exist for the TestSession class.
|
263
286
|
class TestSession < Rack::Session::Abstract::SessionHash #:nodoc:
|
@@ -568,10 +591,13 @@ module ActionController
|
|
568
591
|
|
569
592
|
name = @request.parameters[:action]
|
570
593
|
|
594
|
+
@controller.recycle!
|
571
595
|
@controller.process(name)
|
572
596
|
|
573
597
|
if cookies = @request.env['action_dispatch.cookies']
|
574
|
-
|
598
|
+
unless @response.committed?
|
599
|
+
cookies.write(@response)
|
600
|
+
end
|
575
601
|
end
|
576
602
|
@response.prepare!
|
577
603
|
|
@@ -582,13 +608,14 @@ module ActionController
|
|
582
608
|
end
|
583
609
|
|
584
610
|
def setup_controller_request_and_response
|
585
|
-
@request = build_request
|
586
|
-
@response = build_response
|
587
|
-
@response.request = @request
|
588
|
-
|
589
611
|
@controller = nil unless defined? @controller
|
590
612
|
|
613
|
+
response_klass = TestResponse
|
614
|
+
|
591
615
|
if klass = self.class.controller_class
|
616
|
+
if klass < ActionController::Live
|
617
|
+
response_klass = LiveTestResponse
|
618
|
+
end
|
592
619
|
unless @controller
|
593
620
|
begin
|
594
621
|
@controller = klass.new
|
@@ -598,6 +625,10 @@ module ActionController
|
|
598
625
|
end
|
599
626
|
end
|
600
627
|
|
628
|
+
@request = build_request
|
629
|
+
@response = build_response response_klass
|
630
|
+
@response.request = @request
|
631
|
+
|
601
632
|
if @controller
|
602
633
|
@controller.request = @request
|
603
634
|
@controller.params = {}
|
@@ -608,8 +639,8 @@ module ActionController
|
|
608
639
|
TestRequest.new
|
609
640
|
end
|
610
641
|
|
611
|
-
def build_response
|
612
|
-
|
642
|
+
def build_response(klass)
|
643
|
+
klass.new
|
613
644
|
end
|
614
645
|
|
615
646
|
included do
|
data/lib/action_dispatch.rb
CHANGED
@@ -63,8 +63,6 @@ module ActionDispatch # :nodoc:
|
|
63
63
|
# content you're giving them, so we need to send that along.
|
64
64
|
attr_accessor :charset
|
65
65
|
|
66
|
-
attr_accessor :no_content_type # :nodoc:
|
67
|
-
|
68
66
|
CONTENT_TYPE = "Content-Type".freeze
|
69
67
|
SET_COOKIE = "Set-Cookie".freeze
|
70
68
|
LOCATION = "Location".freeze
|
@@ -93,7 +91,10 @@ module ActionDispatch # :nodoc:
|
|
93
91
|
end
|
94
92
|
|
95
93
|
def each(&block)
|
96
|
-
@
|
94
|
+
@response.sending!
|
95
|
+
x = @buf.each(&block)
|
96
|
+
@response.sent!
|
97
|
+
x
|
97
98
|
end
|
98
99
|
|
99
100
|
def close
|
@@ -120,6 +121,8 @@ module ActionDispatch # :nodoc:
|
|
120
121
|
@blank = false
|
121
122
|
@cv = new_cond
|
122
123
|
@committed = false
|
124
|
+
@sending = false
|
125
|
+
@sent = false
|
123
126
|
@content_type = nil
|
124
127
|
@charset = nil
|
125
128
|
|
@@ -140,17 +143,37 @@ module ActionDispatch # :nodoc:
|
|
140
143
|
end
|
141
144
|
end
|
142
145
|
|
146
|
+
def await_sent
|
147
|
+
synchronize { @cv.wait_until { @sent } }
|
148
|
+
end
|
149
|
+
|
143
150
|
def commit!
|
144
151
|
synchronize do
|
152
|
+
before_committed
|
145
153
|
@committed = true
|
146
154
|
@cv.broadcast
|
147
155
|
end
|
148
156
|
end
|
149
157
|
|
150
|
-
def
|
151
|
-
|
158
|
+
def sending!
|
159
|
+
synchronize do
|
160
|
+
before_sending
|
161
|
+
@sending = true
|
162
|
+
@cv.broadcast
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def sent!
|
167
|
+
synchronize do
|
168
|
+
@sent = true
|
169
|
+
@cv.broadcast
|
170
|
+
end
|
152
171
|
end
|
153
172
|
|
173
|
+
def sending?; synchronize { @sending }; end
|
174
|
+
def committed?; synchronize { @committed }; end
|
175
|
+
def sent?; synchronize { @sent }; end
|
176
|
+
|
154
177
|
# Sets the HTTP status code.
|
155
178
|
def status=(status)
|
156
179
|
@status = Rack::Utils.status_code(status)
|
@@ -275,6 +298,12 @@ module ActionDispatch # :nodoc:
|
|
275
298
|
|
276
299
|
private
|
277
300
|
|
301
|
+
def before_committed
|
302
|
+
end
|
303
|
+
|
304
|
+
def before_sending
|
305
|
+
end
|
306
|
+
|
278
307
|
def merge_default_headers(original, default)
|
279
308
|
return original unless default.respond_to?(:merge)
|
280
309
|
|
@@ -305,17 +334,8 @@ module ActionDispatch # :nodoc:
|
|
305
334
|
!@sending_file && @charset != false
|
306
335
|
end
|
307
336
|
|
308
|
-
def remove_content_type!
|
309
|
-
headers.delete CONTENT_TYPE
|
310
|
-
end
|
311
|
-
|
312
337
|
def rack_response(status, header)
|
313
|
-
|
314
|
-
remove_content_type!
|
315
|
-
else
|
316
|
-
assign_default_content_type_and_charset!(header)
|
317
|
-
end
|
318
|
-
|
338
|
+
assign_default_content_type_and_charset!(header)
|
319
339
|
handle_conditional_get!
|
320
340
|
|
321
341
|
header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
|
@@ -237,6 +237,15 @@ module ActionDispatch
|
|
237
237
|
@secure = secure
|
238
238
|
@options = options
|
239
239
|
@cookies = {}
|
240
|
+
@committed = false
|
241
|
+
end
|
242
|
+
|
243
|
+
def committed?; @committed; end
|
244
|
+
|
245
|
+
def commit!
|
246
|
+
@committed = true
|
247
|
+
@set_cookies.freeze
|
248
|
+
@delete_cookies.freeze
|
240
249
|
end
|
241
250
|
|
242
251
|
def each(&block)
|
@@ -336,8 +345,8 @@ module ActionDispatch
|
|
336
345
|
end
|
337
346
|
|
338
347
|
def recycle! #:nodoc:
|
339
|
-
@set_cookies
|
340
|
-
@delete_cookies
|
348
|
+
@set_cookies = {}
|
349
|
+
@delete_cookies = {}
|
341
350
|
end
|
342
351
|
|
343
352
|
mattr_accessor :always_write_cookie
|
@@ -551,9 +560,11 @@ module ActionDispatch
|
|
551
560
|
status, headers, body = @app.call(env)
|
552
561
|
|
553
562
|
if cookie_jar = env['action_dispatch.cookies']
|
554
|
-
cookie_jar.
|
555
|
-
|
556
|
-
|
563
|
+
unless cookie_jar.committed?
|
564
|
+
cookie_jar.write(headers)
|
565
|
+
if headers[HTTP_HEADER].respond_to?(:join)
|
566
|
+
headers[HTTP_HEADER] = headers[HTTP_HEADER].join("\n")
|
567
|
+
end
|
557
568
|
end
|
558
569
|
end
|
559
570
|
|
@@ -51,7 +51,7 @@ module ActionDispatch
|
|
51
51
|
# decode signed cookies generated by your app in external applications or
|
52
52
|
# Javascript before upgrading.
|
53
53
|
#
|
54
|
-
# Note that changing
|
54
|
+
# Note that changing the secret key will invalidate all existing sessions!
|
55
55
|
class CookieStore < Rack::Session::Abstract::ID
|
56
56
|
include Compatibility
|
57
57
|
include StaleSessionCheck
|
@@ -708,7 +708,8 @@ module ActionDispatch
|
|
708
708
|
options[:constraints] ||= {}
|
709
709
|
|
710
710
|
unless shallow?
|
711
|
-
options[:shallow_path]
|
711
|
+
options[:shallow_path] ||= options[:path] if options.key?(:path)
|
712
|
+
options[:shallow_prefix] ||= options[:as] if options.key?(:as)
|
712
713
|
end
|
713
714
|
|
714
715
|
if options[:constraints].is_a?(Hash)
|
@@ -792,9 +793,16 @@ module ActionDispatch
|
|
792
793
|
# end
|
793
794
|
def namespace(path, options = {})
|
794
795
|
path = path.to_s
|
795
|
-
|
796
|
-
|
797
|
-
|
796
|
+
|
797
|
+
defaults = {
|
798
|
+
module: path,
|
799
|
+
path: options.fetch(:path, path),
|
800
|
+
as: options.fetch(:as, path),
|
801
|
+
shallow_path: options.fetch(:path, path),
|
802
|
+
shallow_prefix: options.fetch(:as, path)
|
803
|
+
}
|
804
|
+
|
805
|
+
scope(defaults.merge!(options)) { yield }
|
798
806
|
end
|
799
807
|
|
800
808
|
# === Parameter Restriction
|
@@ -1323,8 +1331,10 @@ module ActionDispatch
|
|
1323
1331
|
end
|
1324
1332
|
|
1325
1333
|
with_scope_level(:member) do
|
1326
|
-
|
1327
|
-
yield
|
1334
|
+
if shallow?
|
1335
|
+
shallow_scope(parent_resource.member_scope) { yield }
|
1336
|
+
else
|
1337
|
+
scope(parent_resource.member_scope) { yield }
|
1328
1338
|
end
|
1329
1339
|
end
|
1330
1340
|
end
|
@@ -1347,16 +1357,8 @@ module ActionDispatch
|
|
1347
1357
|
end
|
1348
1358
|
|
1349
1359
|
with_scope_level(:nested) do
|
1350
|
-
if shallow?
|
1351
|
-
|
1352
|
-
if @scope[:shallow_path].blank?
|
1353
|
-
scope(parent_resource.nested_scope, nested_options) { yield }
|
1354
|
-
else
|
1355
|
-
scope(@scope[:shallow_path], :as => @scope[:shallow_prefix]) do
|
1356
|
-
scope(parent_resource.nested_scope, nested_options) { yield }
|
1357
|
-
end
|
1358
|
-
end
|
1359
|
-
end
|
1360
|
+
if shallow? && nesting_depth > 1
|
1361
|
+
shallow_scope(parent_resource.nested_scope, nested_options) { yield }
|
1360
1362
|
else
|
1361
1363
|
scope(parent_resource.nested_scope, nested_options) { yield }
|
1362
1364
|
end
|
@@ -1558,21 +1560,23 @@ module ActionDispatch
|
|
1558
1560
|
end
|
1559
1561
|
end
|
1560
1562
|
|
1561
|
-
def with_scope_level(kind
|
1563
|
+
def with_scope_level(kind)
|
1562
1564
|
old, @scope[:scope_level] = @scope[:scope_level], kind
|
1563
|
-
old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource
|
1564
1565
|
yield
|
1565
1566
|
ensure
|
1566
1567
|
@scope[:scope_level] = old
|
1567
|
-
@scope[:scope_level_resource] = old_resource
|
1568
1568
|
end
|
1569
1569
|
|
1570
1570
|
def resource_scope(kind, resource) #:nodoc:
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1571
|
+
old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource
|
1572
|
+
@nesting.push(resource)
|
1573
|
+
|
1574
|
+
with_scope_level(kind) do
|
1575
|
+
scope(parent_resource.resource_scope) { yield }
|
1575
1576
|
end
|
1577
|
+
ensure
|
1578
|
+
@nesting.pop
|
1579
|
+
@scope[:scope_level_resource] = old_resource
|
1576
1580
|
end
|
1577
1581
|
|
1578
1582
|
def nested_options #:nodoc:
|
@@ -1584,6 +1588,10 @@ module ActionDispatch
|
|
1584
1588
|
options
|
1585
1589
|
end
|
1586
1590
|
|
1591
|
+
def nesting_depth #:nodoc:
|
1592
|
+
@nesting.size
|
1593
|
+
end
|
1594
|
+
|
1587
1595
|
def param_constraint? #:nodoc:
|
1588
1596
|
@scope[:constraints] && @scope[:constraints][parent_resource.param].is_a?(Regexp)
|
1589
1597
|
end
|
@@ -1596,18 +1604,20 @@ module ActionDispatch
|
|
1596
1604
|
flag && resource_method_scope? && CANONICAL_ACTIONS.include?(action.to_s)
|
1597
1605
|
end
|
1598
1606
|
|
1599
|
-
def
|
1600
|
-
|
1607
|
+
def shallow_scope(path, options = {}) #:nodoc:
|
1608
|
+
old_name_prefix, old_path = @scope[:as], @scope[:path]
|
1609
|
+
@scope[:as], @scope[:path] = @scope[:shallow_prefix], @scope[:shallow_path]
|
1610
|
+
|
1611
|
+
scope(path, options) { yield }
|
1612
|
+
ensure
|
1613
|
+
@scope[:as], @scope[:path] = old_name_prefix, old_path
|
1601
1614
|
end
|
1602
1615
|
|
1603
1616
|
def path_for_action(action, path) #:nodoc:
|
1604
|
-
prefix = shallow_scoping? ?
|
1605
|
-
"#{@scope[:shallow_path]}/#{parent_resource.shallow_scope}" : @scope[:path]
|
1606
|
-
|
1607
1617
|
if canonical_action?(action, path.blank?)
|
1608
|
-
|
1618
|
+
@scope[:path].to_s
|
1609
1619
|
else
|
1610
|
-
"#{
|
1620
|
+
"#{@scope[:path]}/#{action_path(action, path)}"
|
1611
1621
|
end
|
1612
1622
|
end
|
1613
1623
|
|
@@ -1645,7 +1655,7 @@ module ActionDispatch
|
|
1645
1655
|
when :new
|
1646
1656
|
[prefix, :new, name_prefix, member_name]
|
1647
1657
|
when :member
|
1648
|
-
[prefix,
|
1658
|
+
[prefix, name_prefix, member_name]
|
1649
1659
|
when :root
|
1650
1660
|
[name_prefix, collection_name, prefix]
|
1651
1661
|
else
|
@@ -1786,6 +1796,7 @@ module ActionDispatch
|
|
1786
1796
|
@set = set
|
1787
1797
|
@scope = { :path_names => @set.resources_path_names }
|
1788
1798
|
@concerns = {}
|
1799
|
+
@nesting = []
|
1789
1800
|
end
|
1790
1801
|
|
1791
1802
|
include Base
|
@@ -291,7 +291,7 @@ module ActionDispatch
|
|
291
291
|
# so is this custom message really needed?
|
292
292
|
message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size}.)
|
293
293
|
if count
|
294
|
-
assert_equal matches.size,
|
294
|
+
assert_equal count, matches.size, message
|
295
295
|
else
|
296
296
|
assert_operator matches.size, :>=, min, message if min
|
297
297
|
assert_operator matches.size, :<=, max, message if max
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActionPack
|
2
|
+
# Returns the version of the currently loaded ActionPack as a <tt>Gem::Version</tt>
|
3
|
+
def self.gem_version
|
4
|
+
Gem::Version.new VERSION::STRING
|
5
|
+
end
|
6
|
+
|
7
|
+
module VERSION
|
8
|
+
MAJOR = 4
|
9
|
+
MINOR = 1
|
10
|
+
TINY = 0
|
11
|
+
PRE = "rc2"
|
12
|
+
|
13
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
14
|
+
end
|
15
|
+
end
|
data/lib/action_pack/version.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
+
require_relative 'gem_version'
|
2
|
+
|
1
3
|
module ActionPack
|
2
|
-
# Returns the version of the currently loaded ActionPack as a Gem::Version
|
4
|
+
# Returns the version of the currently loaded ActionPack as a <tt>Gem::Version</tt>
|
3
5
|
def self.version
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
module VERSION #:nodoc:
|
8
|
-
MAJOR, MINOR, TINY, PRE = ActionPack.version.segments
|
9
|
-
STRING = ActionPack.version.to_s
|
6
|
+
gem_version
|
10
7
|
end
|
11
8
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.0.
|
4
|
+
version: 4.1.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.1.0.
|
19
|
+
version: 4.1.0.rc2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.1.0.
|
26
|
+
version: 4.1.0.rc2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,28 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.1.0.
|
61
|
+
version: 4.1.0.rc2
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.1.0.
|
68
|
+
version: 4.1.0.rc2
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: activemodel
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 4.1.0.
|
75
|
+
version: 4.1.0.rc2
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 4.1.0.
|
82
|
+
version: 4.1.0.rc2
|
83
83
|
description: Web apps on Rails. Simple, battle-tested conventions for building and
|
84
84
|
testing MVC web applications. Works with any Rack-compatible server.
|
85
85
|
email: david@loudthinking.com
|
@@ -235,6 +235,7 @@ files:
|
|
235
235
|
- lib/action_dispatch/testing/test_request.rb
|
236
236
|
- lib/action_dispatch/testing/test_response.rb
|
237
237
|
- lib/action_pack.rb
|
238
|
+
- lib/action_pack/gem_version.rb
|
238
239
|
- lib/action_pack/version.rb
|
239
240
|
homepage: http://www.rubyonrails.org
|
240
241
|
licenses:
|