actionpack 4.1.1 → 4.1.2.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +85 -0
- data/lib/abstract_controller/rendering.rb +3 -1
- data/lib/action_controller/metal.rb +6 -1
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +15 -3
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +1 -1
- data/lib/action_dispatch/http/mime_type.rb +1 -1
- data/lib/action_dispatch/http/response.rb +3 -0
- data/lib/action_dispatch/http/url.rb +18 -10
- data/lib/action_dispatch/journey/route.rb +4 -0
- data/lib/action_dispatch/journey/router/utils.rb +51 -17
- data/lib/action_dispatch/journey/visitors.rb +17 -4
- data/lib/action_dispatch/middleware/cookies.rb +2 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +8 -0
- data/lib/action_dispatch/middleware/ssl.rb +8 -5
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/routing.rb +1 -0
- data/lib/action_dispatch/routing/mapper.rb +56 -22
- data/lib/action_dispatch/routing/route_set.rb +4 -2
- data/lib/action_dispatch/testing/assertions/response.rb +7 -1
- data/lib/action_dispatch/testing/assertions/selector.rb +3 -3
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +29 -41
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e696e9aea917e1a7a0ce12cc8e365682a661c6d8
|
4
|
+
data.tar.gz: d259d80f6c29728ab611c9d01087415e19a82f46
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 631a18596b298cd0f1655d001994579bcc17297cdf47a2304474852fb4f43976116b47ffaf21fe6836c75148fcbb90c074bb85fa27ddfde4bf0bf76aeba58326
|
7
|
+
data.tar.gz: b794e4f3045572405883896d1bbe6aab5006cd376c057326aa7d8fef5d2bb083ecfd990bb851904f931df858e250ec217463358a7fd7ae09a8dced8ac6042965
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,77 @@
|
|
1
|
+
## Rails 4.1.2 (May 27, 2014) ##
|
2
|
+
|
3
|
+
* Fix URL generation with `:trailing_slash` such that it does not add
|
4
|
+
a trailing slash after `.:format`
|
5
|
+
|
6
|
+
*Dan Langevin*
|
7
|
+
|
8
|
+
* Fixed an issue with migrating legacy json cookies.
|
9
|
+
|
10
|
+
Previously, the `VerifyAndUpgradeLegacySignedMessage` assumes all incoming
|
11
|
+
cookies are marshal-encoded. This is not the case when `secret_token` is
|
12
|
+
used in conjunction with the `:json` or `:hybrid` serializer.
|
13
|
+
|
14
|
+
In those case, when upgrading to use `secret_key_base`, this would cause a
|
15
|
+
`TypeError: incompatible marshal file format` and a 500 error for the user.
|
16
|
+
|
17
|
+
Fixes #14774.
|
18
|
+
|
19
|
+
*Godfrey Chan*
|
20
|
+
|
21
|
+
* `http_basic_authenticate_with` only check the autentication if the schema is
|
22
|
+
`Basic`.
|
23
|
+
|
24
|
+
Fixes #10257.
|
25
|
+
|
26
|
+
*tomykaira*
|
27
|
+
|
28
|
+
* Fix `'Stack level too deep'` when rendering `head :ok` in an action method
|
29
|
+
called 'status' in a controller.
|
30
|
+
|
31
|
+
Fixes #13905.
|
32
|
+
|
33
|
+
*Christiaan Van den Poel*
|
34
|
+
|
35
|
+
* Always use the provided port if the protocol is relative.
|
36
|
+
|
37
|
+
Fixes #15043.
|
38
|
+
|
39
|
+
*Guilherme Cavalcanti*, *Andrew White*
|
40
|
+
|
41
|
+
* Append link to bad code to backtrace when exception is `SyntaxError`.
|
42
|
+
|
43
|
+
*Boris Kuznetsov*
|
44
|
+
|
45
|
+
* Make URL escaping more consistent:
|
46
|
+
|
47
|
+
1. Escape '%' characters in URLs - only unescaped data should be passed to URL helpers
|
48
|
+
2. Add an `escape_segment` helper to `Router::Utils` that escapes '/' characters
|
49
|
+
3. Use `escape_segment` rather than `escape_fragment` in optimized URL generation
|
50
|
+
4. Use `escape_segment` rather than `escape_path` in URL generation
|
51
|
+
|
52
|
+
For point 4 there are two exceptions. Firstly, when a route uses wildcard segments
|
53
|
+
(e.g. `*foo`) then we use `escape_path` as the value may contain '/' characters. This
|
54
|
+
means that wildcard routes can't be optimized. Secondly, if a `:controller` segment
|
55
|
+
is used in the path then this uses `escape_path` as the controller may be namespaced.
|
56
|
+
|
57
|
+
Fixes #14629, #14636 and #14070.
|
58
|
+
|
59
|
+
*Andrew White*, *Edho Arief*
|
60
|
+
|
61
|
+
* Returns null type format when format is not know and controller is using `any`
|
62
|
+
format block.
|
63
|
+
|
64
|
+
Fixes #14462.
|
65
|
+
|
66
|
+
*Rafael Mendonça França*
|
67
|
+
|
68
|
+
* Only make deeply nested routes shallow when parent is shallow.
|
69
|
+
|
70
|
+
Fixes #14684.
|
71
|
+
|
72
|
+
*Andrew White*, *James Coglan*
|
73
|
+
|
74
|
+
|
1
75
|
## Rails 4.1.1 (May 6, 2014) ##
|
2
76
|
|
3
77
|
* Only accept actions without File::SEPARATOR in the name.
|
@@ -18,6 +92,17 @@
|
|
18
92
|
|
19
93
|
*Vishal Lal*
|
20
94
|
|
95
|
+
* The method `shallow?` returns false if the parent resource is a singleton so
|
96
|
+
we need to check if we're not inside a nested scope before copying the :path
|
97
|
+
and :as options to their shallow equivalents.
|
98
|
+
|
99
|
+
Fixes #14388.
|
100
|
+
|
101
|
+
*Andrew White*
|
102
|
+
|
103
|
+
|
104
|
+
## Rails 4.1.0 (April 8, 2014) ##
|
105
|
+
|
21
106
|
* Fix URL generation in controller tests with request-dependent
|
22
107
|
`default_url_options` methods.
|
23
108
|
|
@@ -106,7 +106,9 @@ module AbstractController
|
|
106
106
|
def _normalize_render(*args, &block)
|
107
107
|
options = _normalize_args(*args, &block)
|
108
108
|
#TODO: remove defined? when we restore AP <=> AV dependency
|
109
|
-
|
109
|
+
if defined?(request) && request && request.variant.present?
|
110
|
+
options[:variant] = request.variant
|
111
|
+
end
|
110
112
|
_normalize_options(options)
|
111
113
|
options
|
112
114
|
end
|
@@ -70,7 +70,8 @@ module ActionController
|
|
70
70
|
# can do the following:
|
71
71
|
#
|
72
72
|
# class HelloController < ActionController::Metal
|
73
|
-
# include
|
73
|
+
# include AbstractController::Rendering
|
74
|
+
# include ActionView::Layouts
|
74
75
|
# append_view_path "#{Rails.root}/app/views"
|
75
76
|
#
|
76
77
|
# def index
|
@@ -231,5 +232,9 @@ module ActionController
|
|
231
232
|
new.dispatch(name, klass.new(env))
|
232
233
|
end
|
233
234
|
end
|
235
|
+
|
236
|
+
def _status_code
|
237
|
+
@_status
|
238
|
+
end
|
234
239
|
end
|
235
240
|
end
|
@@ -27,7 +27,7 @@ module ActionController
|
|
27
27
|
self.status = status
|
28
28
|
self.location = url_for(location) if location
|
29
29
|
|
30
|
-
if include_content?(self.
|
30
|
+
if include_content?(self._status_code)
|
31
31
|
self.content_type = content_type || (Mime[formats.first] if formats)
|
32
32
|
self.response.charset = false if self.response
|
33
33
|
self.response_body = " "
|
@@ -90,17 +90,29 @@ module ActionController
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def authenticate(request, &login_procedure)
|
93
|
-
|
93
|
+
if has_basic_credentials?(request)
|
94
94
|
login_procedure.call(*user_name_and_password(request))
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
def has_basic_credentials?(request)
|
99
|
+
request.authorization.present? && (auth_scheme(request) == 'Basic')
|
100
|
+
end
|
101
|
+
|
98
102
|
def user_name_and_password(request)
|
99
|
-
decode_credentials(request).split(
|
103
|
+
decode_credentials(request).split(':', 2)
|
100
104
|
end
|
101
105
|
|
102
106
|
def decode_credentials(request)
|
103
|
-
::Base64.decode64(request
|
107
|
+
::Base64.decode64(auth_param(request) || '')
|
108
|
+
end
|
109
|
+
|
110
|
+
def auth_scheme(request)
|
111
|
+
request.authorization.split(' ', 2).first
|
112
|
+
end
|
113
|
+
|
114
|
+
def auth_param(request)
|
115
|
+
request.authorization.split(' ', 2).second
|
104
116
|
end
|
105
117
|
|
106
118
|
def encode_credentials(user_name, password)
|
@@ -6,7 +6,7 @@ module ActionController
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
delegate :headers, :status=, :location=, :content_type=,
|
9
|
-
:status, :location, :content_type, :to => "@_response"
|
9
|
+
:status, :location, :content_type, :_status_code, :to => "@_response"
|
10
10
|
|
11
11
|
def dispatch(action, request)
|
12
12
|
set_response!(request)
|
@@ -502,7 +502,7 @@ module ActionController
|
|
502
502
|
# end
|
503
503
|
# end
|
504
504
|
#
|
505
|
-
# In order to use <tt>
|
505
|
+
# In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you
|
506
506
|
# will need to specify which nested attributes should be whitelisted.
|
507
507
|
#
|
508
508
|
# class Person
|
@@ -174,7 +174,7 @@ module Mime
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def parse(accept_header)
|
177
|
-
if accept_header
|
177
|
+
if !accept_header.include?(',')
|
178
178
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
179
179
|
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
180
180
|
else
|
@@ -34,19 +34,15 @@ module ActionDispatch
|
|
34
34
|
path = options.delete(:script_name).to_s.chomp("/")
|
35
35
|
path << options.delete(:path).to_s
|
36
36
|
|
37
|
+
add_trailing_slash(path) if options[:trailing_slash]
|
38
|
+
|
37
39
|
params = options[:params].is_a?(Hash) ? options[:params] : options.slice(:params)
|
38
40
|
params.reject! { |_,v| v.to_param.nil? }
|
39
41
|
|
40
42
|
result = build_host_url(options)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
else
|
45
|
-
result << path.sub(/[^\/]\z|\A\z/, '\&/')
|
46
|
-
end
|
47
|
-
else
|
48
|
-
result << path
|
49
|
-
end
|
43
|
+
|
44
|
+
result << path
|
45
|
+
|
50
46
|
result << "?#{params.to_query}" unless params.empty?
|
51
47
|
result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
|
52
48
|
result
|
@@ -54,6 +50,18 @@ module ActionDispatch
|
|
54
50
|
|
55
51
|
private
|
56
52
|
|
53
|
+
def add_trailing_slash(path)
|
54
|
+
# includes querysting
|
55
|
+
if path.include?('?')
|
56
|
+
path.sub!(/\?/, '/\&')
|
57
|
+
# does not have a .format
|
58
|
+
elsif !path.include?(".")
|
59
|
+
path.sub!(/[^\/]\z|\A\z/, '\&/')
|
60
|
+
end
|
61
|
+
|
62
|
+
path
|
63
|
+
end
|
64
|
+
|
57
65
|
def build_host_url(options)
|
58
66
|
if options[:host].blank? && options[:only_path].blank?
|
59
67
|
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
|
@@ -130,7 +138,7 @@ module ActionDispatch
|
|
130
138
|
|
131
139
|
case options[:protocol]
|
132
140
|
when "//"
|
133
|
-
|
141
|
+
options[:port]
|
134
142
|
when "https://"
|
135
143
|
options[:port].to_i == 443 ? nil : options[:port]
|
136
144
|
else
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'uri'
|
2
|
-
|
3
1
|
module ActionDispatch
|
4
2
|
module Journey # :nodoc:
|
5
3
|
class Router # :nodoc:
|
@@ -25,31 +23,67 @@ module ActionDispatch
|
|
25
23
|
|
26
24
|
# URI path and fragment escaping
|
27
25
|
# http://tools.ietf.org/html/rfc3986
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
26
|
+
class UriEncoder # :nodoc:
|
27
|
+
ENCODE = "%%%02X".freeze
|
28
|
+
ENCODING = Encoding::US_ASCII
|
29
|
+
EMPTY = "".force_encoding(ENCODING).freeze
|
30
|
+
DEC2HEX = (0..255).to_a.map{ |i| ENCODE % i }.map{ |s| s.force_encoding(ENCODING) }
|
31
|
+
|
32
|
+
ALPHA = "a-zA-Z".freeze
|
33
|
+
DIGIT = "0-9".freeze
|
34
|
+
UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~".freeze
|
35
|
+
SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;=".freeze
|
36
|
+
|
37
|
+
ESCAPED = /%[a-zA-Z0-9]{2}/.freeze
|
38
|
+
|
39
|
+
FRAGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/\?]/.freeze
|
40
|
+
SEGMENT = /[^#{UNRESERVED}#{SUB_DELIMS}:@]/.freeze
|
41
|
+
PATH = /[^#{UNRESERVED}#{SUB_DELIMS}:@\/]/.freeze
|
42
|
+
|
43
|
+
def escape_fragment(fragment)
|
44
|
+
escape(fragment, FRAGMENT)
|
45
|
+
end
|
46
|
+
|
47
|
+
def escape_path(path)
|
48
|
+
escape(path, PATH)
|
49
|
+
end
|
50
|
+
|
51
|
+
def escape_segment(segment)
|
52
|
+
escape(segment, SEGMENT)
|
53
|
+
end
|
54
|
+
|
55
|
+
def unescape_uri(uri)
|
56
|
+
uri.gsub(ESCAPED) { [$&[1, 2].hex].pack('C') }.force_encoding(uri.encoding)
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
def escape(component, pattern)
|
61
|
+
component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(ENCODING)
|
62
|
+
end
|
63
|
+
|
64
|
+
def percent_encode(unsafe)
|
65
|
+
safe = EMPTY.dup
|
66
|
+
unsafe.each_byte { |b| safe << DEC2HEX[b] }
|
67
|
+
safe
|
68
|
+
end
|
39
69
|
end
|
40
70
|
|
41
|
-
|
71
|
+
ENCODER = UriEncoder.new
|
42
72
|
|
43
73
|
def self.escape_path(path)
|
44
|
-
|
74
|
+
ENCODER.escape_path(path.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.escape_segment(segment)
|
78
|
+
ENCODER.escape_segment(segment.to_s)
|
45
79
|
end
|
46
80
|
|
47
81
|
def self.escape_fragment(fragment)
|
48
|
-
|
82
|
+
ENCODER.escape_fragment(fragment.to_s)
|
49
83
|
end
|
50
84
|
|
51
85
|
def self.unescape_uri(uri)
|
52
|
-
|
86
|
+
ENCODER.unescape_uri(uri)
|
53
87
|
end
|
54
88
|
end
|
55
89
|
end
|
@@ -114,19 +114,26 @@ module ActionDispatch
|
|
114
114
|
end
|
115
115
|
|
116
116
|
private
|
117
|
+
def escape_path(value)
|
118
|
+
Router::Utils.escape_path(value)
|
119
|
+
end
|
120
|
+
|
121
|
+
def escape_segment(value)
|
122
|
+
Router::Utils.escape_segment(value)
|
123
|
+
end
|
117
124
|
|
118
125
|
def visit(node, optional = false)
|
119
126
|
case node.type
|
120
127
|
when :LITERAL, :SLASH, :DOT
|
121
128
|
node.left
|
122
129
|
when :STAR
|
123
|
-
|
130
|
+
visit_STAR(node.left)
|
124
131
|
when :GROUP
|
125
132
|
visit(node.left, true)
|
126
133
|
when :CAT
|
127
134
|
visit_CAT(node, optional)
|
128
135
|
when :SYMBOL
|
129
|
-
visit_SYMBOL(node)
|
136
|
+
visit_SYMBOL(node, node.to_sym)
|
130
137
|
end
|
131
138
|
end
|
132
139
|
|
@@ -141,9 +148,15 @@ module ActionDispatch
|
|
141
148
|
end
|
142
149
|
end
|
143
150
|
|
144
|
-
def
|
151
|
+
def visit_STAR(node)
|
145
152
|
if value = options[node.to_sym]
|
146
|
-
|
153
|
+
escape_path(value)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def visit_SYMBOL(node, name)
|
158
|
+
if value = options[name]
|
159
|
+
name == :controller ? escape_path(value) : escape_segment(value)
|
147
160
|
end
|
148
161
|
end
|
149
162
|
end
|
@@ -176,11 +176,11 @@ module ActionDispatch
|
|
176
176
|
module VerifyAndUpgradeLegacySignedMessage
|
177
177
|
def initialize(*args)
|
178
178
|
super
|
179
|
-
@legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token])
|
179
|
+
@legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token], serializer: NullSerializer)
|
180
180
|
end
|
181
181
|
|
182
182
|
def verify_and_upgrade_legacy_signed_message(name, signed_message)
|
183
|
-
@legacy_verifier.verify(signed_message).tap do |value|
|
183
|
+
deserialize(name, @legacy_verifier.verify(signed_message)).tap do |value|
|
184
184
|
self[name] = { value: value }
|
185
185
|
end
|
186
186
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
@@ -32,6 +32,8 @@ module ActionDispatch
|
|
32
32
|
def initialize(env, exception)
|
33
33
|
@env = env
|
34
34
|
@exception = original_exception(exception)
|
35
|
+
|
36
|
+
expand_backtrace if exception.is_a?(SyntaxError) || exception.try(:original_exception).try(:is_a?, SyntaxError)
|
35
37
|
end
|
36
38
|
|
37
39
|
def rescue_template
|
@@ -104,5 +106,11 @@ module ActionDispatch
|
|
104
106
|
end
|
105
107
|
end
|
106
108
|
end
|
109
|
+
|
110
|
+
def expand_backtrace
|
111
|
+
@exception.backtrace.unshift(
|
112
|
+
@exception.to_s.split("\n")
|
113
|
+
).flatten!
|
114
|
+
end
|
107
115
|
end
|
108
116
|
end
|
@@ -32,11 +32,14 @@ module ActionDispatch
|
|
32
32
|
|
33
33
|
private
|
34
34
|
def redirect_to_https(request)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
host = @host || request.host
|
36
|
+
port = @port || request.port
|
37
|
+
|
38
|
+
location = "https://#{host}"
|
39
|
+
location << ":#{port}" if port != 80
|
40
|
+
location << request.fullpath
|
41
|
+
|
42
|
+
headers = { 'Content-Type' => 'text/html', 'Location' => location }
|
40
43
|
|
41
44
|
[301, headers, []]
|
42
45
|
end
|
@@ -122,7 +122,7 @@
|
|
122
122
|
// On key press perform a search for matching paths
|
123
123
|
pathElem.onkeyup = function(e){
|
124
124
|
var path = sanitizePath(pathElem.value),
|
125
|
-
defaultText = '<tr><th colspan="4">Paths Matching (' + path + '):</th></tr>';
|
125
|
+
defaultText = '<tr><th colspan="4">Paths Matching (' + escape(path) + '):</th></tr>';
|
126
126
|
|
127
127
|
// Clear out results section
|
128
128
|
selectedSection.innerHTML= defaultText;
|
@@ -340,18 +340,35 @@ module ActionDispatch
|
|
340
340
|
match '/', { :as => :root, :via => :get }.merge!(options)
|
341
341
|
end
|
342
342
|
|
343
|
-
# Matches a url pattern to one or more routes.
|
344
|
-
# are interpreted as url query parameters and thus available as +params+
|
345
|
-
# in an action:
|
343
|
+
# Matches a url pattern to one or more routes.
|
346
344
|
#
|
345
|
+
# You should not use the `match` method in your router
|
346
|
+
# without specifying an HTTP method.
|
347
|
+
#
|
348
|
+
# If you want to expose your action to both GET and POST, use:
|
349
|
+
#
|
347
350
|
# # sets :controller, :action and :id in params
|
348
|
-
# match ':controller/:action/:id'
|
351
|
+
# match ':controller/:action/:id', via: [:get, :post]
|
352
|
+
#
|
353
|
+
# Note that +:controller+, +:action+, +:id+ are interpreted as url query
|
354
|
+
# parameters and thus available as +params+
|
355
|
+
# in an action.
|
356
|
+
#
|
357
|
+
# If you want to expose your action to GET, use `get` in the router:
|
358
|
+
#
|
359
|
+
# Instead of:
|
360
|
+
#
|
361
|
+
# match ":controller/:action/:id"
|
362
|
+
#
|
363
|
+
# Do:
|
364
|
+
#
|
365
|
+
# get ":controller/:action/:id"
|
349
366
|
#
|
350
367
|
# Two of these symbols are special, +:controller+ maps to the controller
|
351
368
|
# and +:action+ to the controller's action. A pattern can also map
|
352
369
|
# wildcard segments (globs) to params:
|
353
370
|
#
|
354
|
-
#
|
371
|
+
# get 'songs/*category/:title', to: 'songs#show'
|
355
372
|
#
|
356
373
|
# # 'songs/rock/classic/stairway-to-heaven' sets
|
357
374
|
# # params[:category] = 'rock/classic'
|
@@ -360,17 +377,17 @@ module ActionDispatch
|
|
360
377
|
# When a pattern points to an internal route, the route's +:action+ and
|
361
378
|
# +:controller+ should be set in options or hash shorthand. Examples:
|
362
379
|
#
|
363
|
-
# match 'photos/:id' => 'photos#show'
|
364
|
-
# match 'photos/:id', to: 'photos#show'
|
365
|
-
# match 'photos/:id', controller: 'photos', action: 'show'
|
380
|
+
# match 'photos/:id' => 'photos#show', via: [:get]
|
381
|
+
# match 'photos/:id', to: 'photos#show', via: [:get]
|
382
|
+
# match 'photos/:id', controller: 'photos', action: 'show', via: [:get]
|
366
383
|
#
|
367
384
|
# A pattern can also point to a +Rack+ endpoint i.e. anything that
|
368
385
|
# responds to +call+:
|
369
386
|
#
|
370
|
-
# match 'photos/:id', to: lambda {|hash| [200, {}, ["Coming soon"]] }
|
371
|
-
# match 'photos/:id', to: PhotoRackApp
|
387
|
+
# match 'photos/:id', to: lambda {|hash| [200, {}, ["Coming soon"]] }, via: [:get]
|
388
|
+
# match 'photos/:id', to: PhotoRackApp, via: [:get]
|
372
389
|
# # Yes, controller actions are just rack endpoints
|
373
|
-
# match 'photos/:id', to: PhotosController.action(:show)
|
390
|
+
# match 'photos/:id', to: PhotosController.action(:show), via: [:get]
|
374
391
|
#
|
375
392
|
# Because requesting various HTTP verbs with a single action has security
|
376
393
|
# implications, you must either specify the actions in
|
@@ -393,7 +410,7 @@ module ActionDispatch
|
|
393
410
|
# [:module]
|
394
411
|
# The namespace for :controller.
|
395
412
|
#
|
396
|
-
# match 'path', to: 'c#a', module: 'sekret', controller: 'posts'
|
413
|
+
# match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: [:get]
|
397
414
|
# # => Sekret::PostsController
|
398
415
|
#
|
399
416
|
# See <tt>Scoping#namespace</tt> for its scope equivalent.
|
@@ -412,9 +429,9 @@ module ActionDispatch
|
|
412
429
|
# Points to a +Rack+ endpoint. Can be an object that responds to
|
413
430
|
# +call+ or a string representing a controller's action.
|
414
431
|
#
|
415
|
-
# match 'path', to: 'controller#action'
|
416
|
-
# match 'path', to: lambda { |env| [200, {}, ["Success!"]] }
|
417
|
-
# match 'path', to: RackApp
|
432
|
+
# match 'path', to: 'controller#action', via: [:get]
|
433
|
+
# match 'path', to: lambda { |env| [200, {}, ["Success!"]] }, via: [:get]
|
434
|
+
# match 'path', to: RackApp, via: [:get]
|
418
435
|
#
|
419
436
|
# [:on]
|
420
437
|
# Shorthand for wrapping routes in a specific RESTful context. Valid
|
@@ -439,14 +456,14 @@ module ActionDispatch
|
|
439
456
|
# other than path can also be specified with any object
|
440
457
|
# that responds to <tt>===</tt> (eg. String, Array, Range, etc.).
|
441
458
|
#
|
442
|
-
# match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }
|
459
|
+
# match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: [:get]
|
443
460
|
#
|
444
|
-
# match 'json_only', constraints: { format: 'json' }
|
461
|
+
# match 'json_only', constraints: { format: 'json' }, via: [:get]
|
445
462
|
#
|
446
463
|
# class Whitelist
|
447
464
|
# def matches?(request) request.remote_ip == '1.2.3.4' end
|
448
465
|
# end
|
449
|
-
# match 'path', to: 'c#a', constraints: Whitelist.new
|
466
|
+
# match 'path', to: 'c#a', constraints: Whitelist.new, via: [:get]
|
450
467
|
#
|
451
468
|
# See <tt>Scoping#constraints</tt> for more examples with its scope
|
452
469
|
# equivalent.
|
@@ -455,7 +472,7 @@ module ActionDispatch
|
|
455
472
|
# Sets defaults for parameters
|
456
473
|
#
|
457
474
|
# # Sets params[:format] to 'jpg' by default
|
458
|
-
# match 'path', to: 'c#a', defaults: { format: 'jpg' }
|
475
|
+
# match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: [:get]
|
459
476
|
#
|
460
477
|
# See <tt>Scoping#defaults</tt> for its scope equivalent.
|
461
478
|
#
|
@@ -464,7 +481,7 @@ module ActionDispatch
|
|
464
481
|
# false, the pattern matches any request prefixed with the given path.
|
465
482
|
#
|
466
483
|
# # Matches any request starting with 'path'
|
467
|
-
# match 'path', to: 'c#a', anchor: false
|
484
|
+
# match 'path', to: 'c#a', anchor: false, via: [:get]
|
468
485
|
#
|
469
486
|
# [:format]
|
470
487
|
# Allows you to specify the default value for optional +format+
|
@@ -707,7 +724,7 @@ module ActionDispatch
|
|
707
724
|
options[:path] = args.flatten.join('/') if args.any?
|
708
725
|
options[:constraints] ||= {}
|
709
726
|
|
710
|
-
unless
|
727
|
+
unless nested_scope?
|
711
728
|
options[:shallow_path] ||= options[:path] if options.key?(:path)
|
712
729
|
options[:shallow_prefix] ||= options[:as] if options.key?(:as)
|
713
730
|
end
|
@@ -991,6 +1008,7 @@ module ActionDispatch
|
|
991
1008
|
@as = options[:as]
|
992
1009
|
@param = (options[:param] || :id).to_sym
|
993
1010
|
@options = options
|
1011
|
+
@shallow = false
|
994
1012
|
end
|
995
1013
|
|
996
1014
|
def default_actions
|
@@ -1051,6 +1069,13 @@ module ActionDispatch
|
|
1051
1069
|
"#{path}/:#{nested_param}"
|
1052
1070
|
end
|
1053
1071
|
|
1072
|
+
def shallow=(value)
|
1073
|
+
@shallow = value
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
def shallow?
|
1077
|
+
@shallow
|
1078
|
+
end
|
1054
1079
|
end
|
1055
1080
|
|
1056
1081
|
class SingletonResource < Resource #:nodoc:
|
@@ -1357,7 +1382,7 @@ module ActionDispatch
|
|
1357
1382
|
end
|
1358
1383
|
|
1359
1384
|
with_scope_level(:nested) do
|
1360
|
-
if shallow? &&
|
1385
|
+
if shallow? && shallow_nesting_depth > 1
|
1361
1386
|
shallow_scope(parent_resource.nested_scope, nested_options) { yield }
|
1362
1387
|
else
|
1363
1388
|
scope(parent_resource.nested_scope, nested_options) { yield }
|
@@ -1547,6 +1572,10 @@ module ActionDispatch
|
|
1547
1572
|
RESOURCE_METHOD_SCOPES.include? @scope[:scope_level]
|
1548
1573
|
end
|
1549
1574
|
|
1575
|
+
def nested_scope? #:nodoc:
|
1576
|
+
@scope[:scope_level] == :nested
|
1577
|
+
end
|
1578
|
+
|
1550
1579
|
def with_exclusive_scope
|
1551
1580
|
begin
|
1552
1581
|
old_name_prefix, old_path = @scope[:as], @scope[:path]
|
@@ -1568,6 +1597,7 @@ module ActionDispatch
|
|
1568
1597
|
end
|
1569
1598
|
|
1570
1599
|
def resource_scope(kind, resource) #:nodoc:
|
1600
|
+
resource.shallow = @scope[:shallow]
|
1571
1601
|
old_resource, @scope[:scope_level_resource] = @scope[:scope_level_resource], resource
|
1572
1602
|
@nesting.push(resource)
|
1573
1603
|
|
@@ -1592,6 +1622,10 @@ module ActionDispatch
|
|
1592
1622
|
@nesting.size
|
1593
1623
|
end
|
1594
1624
|
|
1625
|
+
def shallow_nesting_depth #:nodoc:
|
1626
|
+
@nesting.select(&:shallow?).size
|
1627
|
+
end
|
1628
|
+
|
1595
1629
|
def param_constraint? #:nodoc:
|
1596
1630
|
@scope[:constraints] && @scope[:constraints][parent_resource.param].is_a?(Regexp)
|
1597
1631
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'action_dispatch/journey'
|
2
2
|
require 'forwardable'
|
3
3
|
require 'thread_safe'
|
4
|
+
require 'active_support/concern'
|
4
5
|
require 'active_support/core_ext/object/to_query'
|
5
6
|
require 'active_support/core_ext/hash/slice'
|
6
7
|
require 'active_support/core_ext/module/remove_method'
|
7
8
|
require 'active_support/core_ext/array/extract_options'
|
8
9
|
require 'action_controller/metal/exceptions'
|
10
|
+
require 'action_dispatch/http/request'
|
9
11
|
|
10
12
|
module ActionDispatch
|
11
13
|
module Routing
|
@@ -155,7 +157,7 @@ module ActionDispatch
|
|
155
157
|
end
|
156
158
|
|
157
159
|
def self.optimize_helper?(route)
|
158
|
-
route.requirements.except(:controller, :action).empty?
|
160
|
+
!route.glob? && route.requirements.except(:controller, :action).empty?
|
159
161
|
end
|
160
162
|
|
161
163
|
class OptimizedUrlHelper < UrlHelper # :nodoc:
|
@@ -194,7 +196,7 @@ module ActionDispatch
|
|
194
196
|
end
|
195
197
|
|
196
198
|
def replace_segment(params, segment)
|
197
|
-
Symbol === segment ? @klass.
|
199
|
+
Symbol === segment ? @klass.escape_segment(params[segment]) : segment
|
198
200
|
end
|
199
201
|
|
200
202
|
def optimize_routes_generation?(t)
|
@@ -73,7 +73,13 @@ module ActionDispatch
|
|
73
73
|
if Regexp === fragment
|
74
74
|
fragment
|
75
75
|
else
|
76
|
-
@controller.
|
76
|
+
handle = @controller || Class.new(ActionController::Metal) do
|
77
|
+
include ActionController::Redirecting
|
78
|
+
def initialize(request)
|
79
|
+
@_request = request
|
80
|
+
end
|
81
|
+
end.new(@request)
|
82
|
+
handle._compute_redirect_to_location(fragment)
|
77
83
|
end
|
78
84
|
end
|
79
85
|
end
|
@@ -267,7 +267,7 @@ module ActionDispatch
|
|
267
267
|
text.strip! unless NO_STRIP.include?(match.name)
|
268
268
|
text.sub!(/\A\n/, '') if match.name == "textarea"
|
269
269
|
unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s)
|
270
|
-
content_mismatch ||= sprintf("<%s> expected but was\n<%s
|
270
|
+
content_mismatch ||= sprintf("<%s> expected but was\n<%s>", match_with, text)
|
271
271
|
true
|
272
272
|
end
|
273
273
|
end
|
@@ -276,7 +276,7 @@ module ActionDispatch
|
|
276
276
|
html = match.children.map(&:to_s).join
|
277
277
|
html.strip! unless NO_STRIP.include?(match.name)
|
278
278
|
unless match_with.is_a?(Regexp) ? (html =~ match_with) : (html == match_with.to_s)
|
279
|
-
content_mismatch ||= sprintf("<%s> expected but was\n<%s
|
279
|
+
content_mismatch ||= sprintf("<%s> expected but was\n<%s>", match_with, html)
|
280
280
|
true
|
281
281
|
end
|
282
282
|
end
|
@@ -289,7 +289,7 @@ module ActionDispatch
|
|
289
289
|
|
290
290
|
# FIXME: minitest provides messaging when we use assert_operator,
|
291
291
|
# so is this custom message really needed?
|
292
|
-
message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size}
|
292
|
+
message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size})
|
293
293
|
if count
|
294
294
|
assert_equal count, matches.size, message
|
295
295
|
else
|
metadata
CHANGED
@@ -1,96 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
5
|
-
prerelease:
|
4
|
+
version: 4.1.2.rc1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- David Heinemeier Hansson
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-27 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - '='
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 4.1.
|
19
|
+
version: 4.1.2.rc1
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - '='
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 4.1.
|
26
|
+
version: 4.1.2.rc1
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rack
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- - ~>
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 1.5.2
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- - ~>
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 1.5.2
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rack-test
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- - ~>
|
45
|
+
- - "~>"
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: 0.6.2
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- - ~>
|
52
|
+
- - "~>"
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: 0.6.2
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: actionview
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - '='
|
68
60
|
- !ruby/object:Gem::Version
|
69
|
-
version: 4.1.
|
61
|
+
version: 4.1.2.rc1
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - '='
|
76
67
|
- !ruby/object:Gem::Version
|
77
|
-
version: 4.1.
|
68
|
+
version: 4.1.2.rc1
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: activemodel
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - '='
|
84
74
|
- !ruby/object:Gem::Version
|
85
|
-
version: 4.1.
|
75
|
+
version: 4.1.2.rc1
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - '='
|
92
81
|
- !ruby/object:Gem::Version
|
93
|
-
version: 4.1.
|
82
|
+
version: 4.1.2.rc1
|
94
83
|
description: Web apps on Rails. Simple, battle-tested conventions for building and
|
95
84
|
testing MVC web applications. Works with any Rack-compatible server.
|
96
85
|
email: david@loudthinking.com
|
@@ -99,8 +88,9 @@ extensions: []
|
|
99
88
|
extra_rdoc_files: []
|
100
89
|
files:
|
101
90
|
- CHANGELOG.md
|
102
|
-
- README.rdoc
|
103
91
|
- MIT-LICENSE
|
92
|
+
- README.rdoc
|
93
|
+
- lib/abstract_controller.rb
|
104
94
|
- lib/abstract_controller/asset_paths.rb
|
105
95
|
- lib/abstract_controller/base.rb
|
106
96
|
- lib/abstract_controller/callbacks.rb
|
@@ -111,11 +101,12 @@ files:
|
|
111
101
|
- lib/abstract_controller/rendering.rb
|
112
102
|
- lib/abstract_controller/translation.rb
|
113
103
|
- lib/abstract_controller/url_for.rb
|
114
|
-
- lib/
|
104
|
+
- lib/action_controller.rb
|
115
105
|
- lib/action_controller/base.rb
|
116
|
-
- lib/action_controller/caching/fragments.rb
|
117
106
|
- lib/action_controller/caching.rb
|
107
|
+
- lib/action_controller/caching/fragments.rb
|
118
108
|
- lib/action_controller/log_subscriber.rb
|
109
|
+
- lib/action_controller/metal.rb
|
119
110
|
- lib/action_controller/metal/conditional_get.rb
|
120
111
|
- lib/action_controller/metal/cookies.rb
|
121
112
|
- lib/action_controller/metal/data_streaming.rb
|
@@ -142,13 +133,12 @@ files:
|
|
142
133
|
- lib/action_controller/metal/strong_parameters.rb
|
143
134
|
- lib/action_controller/metal/testing.rb
|
144
135
|
- lib/action_controller/metal/url_for.rb
|
145
|
-
- lib/action_controller/metal.rb
|
146
136
|
- lib/action_controller/middleware.rb
|
147
137
|
- lib/action_controller/model_naming.rb
|
148
138
|
- lib/action_controller/railtie.rb
|
149
139
|
- lib/action_controller/railties/helpers.rb
|
150
140
|
- lib/action_controller/test_case.rb
|
151
|
-
- lib/
|
141
|
+
- lib/action_dispatch.rb
|
152
142
|
- lib/action_dispatch/http/cache.rb
|
153
143
|
- lib/action_dispatch/http/filter_parameters.rb
|
154
144
|
- lib/action_dispatch/http/filter_redirect.rb
|
@@ -163,6 +153,7 @@ files:
|
|
163
153
|
- lib/action_dispatch/http/response.rb
|
164
154
|
- lib/action_dispatch/http/upload.rb
|
165
155
|
- lib/action_dispatch/http/url.rb
|
156
|
+
- lib/action_dispatch/journey.rb
|
166
157
|
- lib/action_dispatch/journey/backwards.rb
|
167
158
|
- lib/action_dispatch/journey/formatter.rb
|
168
159
|
- lib/action_dispatch/journey/gtg/builder.rb
|
@@ -178,16 +169,15 @@ files:
|
|
178
169
|
- lib/action_dispatch/journey/parser_extras.rb
|
179
170
|
- lib/action_dispatch/journey/path/pattern.rb
|
180
171
|
- lib/action_dispatch/journey/route.rb
|
172
|
+
- lib/action_dispatch/journey/router.rb
|
181
173
|
- lib/action_dispatch/journey/router/strexp.rb
|
182
174
|
- lib/action_dispatch/journey/router/utils.rb
|
183
|
-
- lib/action_dispatch/journey/router.rb
|
184
175
|
- lib/action_dispatch/journey/routes.rb
|
185
176
|
- lib/action_dispatch/journey/scanner.rb
|
186
177
|
- lib/action_dispatch/journey/visitors.rb
|
187
178
|
- lib/action_dispatch/journey/visualizer/fsm.css
|
188
179
|
- lib/action_dispatch/journey/visualizer/fsm.js
|
189
180
|
- lib/action_dispatch/journey/visualizer/index.html.erb
|
190
|
-
- lib/action_dispatch/journey.rb
|
191
181
|
- lib/action_dispatch/middleware/callbacks.rb
|
192
182
|
- lib/action_dispatch/middleware/cookies.rb
|
193
183
|
- lib/action_dispatch/middleware/debug_exceptions.rb
|
@@ -226,6 +216,7 @@ files:
|
|
226
216
|
- lib/action_dispatch/railtie.rb
|
227
217
|
- lib/action_dispatch/request/session.rb
|
228
218
|
- lib/action_dispatch/request/utils.rb
|
219
|
+
- lib/action_dispatch/routing.rb
|
229
220
|
- lib/action_dispatch/routing/inspector.rb
|
230
221
|
- lib/action_dispatch/routing/mapper.rb
|
231
222
|
- lib/action_dispatch/routing/polymorphic_routes.rb
|
@@ -233,45 +224,42 @@ files:
|
|
233
224
|
- lib/action_dispatch/routing/route_set.rb
|
234
225
|
- lib/action_dispatch/routing/routes_proxy.rb
|
235
226
|
- lib/action_dispatch/routing/url_for.rb
|
236
|
-
- lib/action_dispatch/
|
227
|
+
- lib/action_dispatch/testing/assertions.rb
|
237
228
|
- lib/action_dispatch/testing/assertions/dom.rb
|
238
229
|
- lib/action_dispatch/testing/assertions/response.rb
|
239
230
|
- lib/action_dispatch/testing/assertions/routing.rb
|
240
231
|
- lib/action_dispatch/testing/assertions/selector.rb
|
241
232
|
- lib/action_dispatch/testing/assertions/tag.rb
|
242
|
-
- lib/action_dispatch/testing/assertions.rb
|
243
233
|
- lib/action_dispatch/testing/integration.rb
|
244
234
|
- lib/action_dispatch/testing/test_process.rb
|
245
235
|
- lib/action_dispatch/testing/test_request.rb
|
246
236
|
- lib/action_dispatch/testing/test_response.rb
|
247
|
-
- lib/
|
237
|
+
- lib/action_pack.rb
|
248
238
|
- lib/action_pack/gem_version.rb
|
249
239
|
- lib/action_pack/version.rb
|
250
|
-
- lib/action_pack.rb
|
251
240
|
homepage: http://www.rubyonrails.org
|
252
241
|
licenses:
|
253
242
|
- MIT
|
243
|
+
metadata: {}
|
254
244
|
post_install_message:
|
255
245
|
rdoc_options: []
|
256
246
|
require_paths:
|
257
247
|
- lib
|
258
248
|
required_ruby_version: !ruby/object:Gem::Requirement
|
259
|
-
none: false
|
260
249
|
requirements:
|
261
|
-
- -
|
250
|
+
- - ">="
|
262
251
|
- !ruby/object:Gem::Version
|
263
252
|
version: 1.9.3
|
264
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
265
|
-
none: false
|
266
254
|
requirements:
|
267
|
-
- -
|
255
|
+
- - ">"
|
268
256
|
- !ruby/object:Gem::Version
|
269
|
-
version:
|
257
|
+
version: 1.3.1
|
270
258
|
requirements:
|
271
259
|
- none
|
272
260
|
rubyforge_project:
|
273
|
-
rubygems_version:
|
261
|
+
rubygems_version: 2.2.2
|
274
262
|
signing_key:
|
275
|
-
specification_version:
|
263
|
+
specification_version: 4
|
276
264
|
summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
|
277
265
|
test_files: []
|