actionpack 4.0.0 → 4.0.1.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 +4 -4
- data/CHANGELOG.md +221 -0
- data/README.rdoc +1 -1
- data/lib/abstract_controller/callbacks.rb +1 -1
- data/lib/abstract_controller/helpers.rb +6 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/metal/flash.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +7 -2
- data/lib/action_controller/test_case.rb +1 -1
- data/lib/action_dispatch/http/mime_type.rb +1 -1
- data/lib/action_dispatch/http/response.rb +3 -1
- data/lib/action_dispatch/journey/formatter.rb +5 -1
- data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -12
- data/lib/action_dispatch/journey/route.rb +12 -0
- data/lib/action_dispatch/journey/router/utils.rb +3 -0
- data/lib/action_dispatch/journey/routes.rb +1 -0
- data/lib/action_dispatch/journey/visitors.rb +5 -2
- data/lib/action_dispatch/middleware/cookies.rb +1 -1
- data/lib/action_dispatch/middleware/params_parser.rb +1 -1
- data/lib/action_dispatch/middleware/remote_ip.rb +1 -1
- data/lib/action_dispatch/middleware/ssl.rb +2 -3
- data/lib/action_dispatch/routing/mapper.rb +5 -0
- data/lib/action_dispatch/routing/redirection.rb +18 -0
- data/lib/action_dispatch/routing/route_set.rb +26 -1
- data/lib/action_dispatch/testing/assertions/dom.rb +4 -4
- data/lib/action_dispatch/testing/test_request.rb +5 -5
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/dependency_tracker.rb +1 -1
- data/lib/action_view/digestor.rb +34 -6
- data/lib/action_view/helpers/date_helper.rb +2 -2
- data/lib/action_view/helpers/form_helper.rb +1 -1
- data/lib/action_view/helpers/form_options_helper.rb +11 -6
- data/lib/action_view/helpers/tags/base.rb +2 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
- data/lib/action_view/helpers/tags/color_field.rb +1 -1
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/label.rb +1 -0
- data/lib/action_view/helpers/tags/text_area.rb +1 -1
- data/lib/action_view/helpers/tags/text_field.rb +2 -2
- data/lib/action_view/helpers/text_helper.rb +3 -2
- data/lib/action_view/helpers/url_helper.rb +4 -3
- data/lib/action_view/railtie.rb +4 -0
- data/lib/action_view/renderer/template_renderer.rb +1 -1
- data/lib/action_view/tasks/dependencies.rake +17 -0
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6c04ba63b482170976504173eb76a7606468917
|
4
|
+
data.tar.gz: cec22e4ca260d29bf97824bb03b607fb8aead200
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01bcd33e7a28dcae4833ce06977d6b540ae2b59d505926b8c95569f70ac2b371a2fe135a7aa87a8219faa1b6309a327f5babc1c884f5d075ead9939ce130a5e9
|
7
|
+
data.tar.gz: ffff6e9d696185d003e9ab97dfe7bb32ba25dcd95a46af76552b4fca01900803b693145b51986642183c3c6d562149b592b782658091874b9374ecb448d334be
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,220 @@
|
|
1
|
+
## Rails 4.0.1.rc1 (October 17, 2013) ##
|
2
|
+
|
3
|
+
* Respect `SCRIPT_NAME` when using `redirect` with a relative path
|
4
|
+
|
5
|
+
Example:
|
6
|
+
# application routes.rb
|
7
|
+
mount BlogEngine => '/blog'
|
8
|
+
|
9
|
+
# engine routes.rb
|
10
|
+
get '/admin' => redirect('admin/dashboard')
|
11
|
+
|
12
|
+
This now redirects to the path `/blog/admin/dashboard`, whereas before it would've
|
13
|
+
generated an invalid url because there would be no slash between the host name and
|
14
|
+
the path. It also allows redirects to work where the application is deployed to a
|
15
|
+
subdirectory of a website.
|
16
|
+
|
17
|
+
Fixes #7977.
|
18
|
+
|
19
|
+
*Andrew White*
|
20
|
+
|
21
|
+
* Fix `ActionDispatch::RemoteIp::GetIp#calculate_ip` to only check for spoofing
|
22
|
+
attacks if both `HTTP_CLIENT_IP` and `HTTP_X_FORWARDED_FOR` are set.
|
23
|
+
|
24
|
+
Fixes #10844.
|
25
|
+
|
26
|
+
*Tamir Duberstein*
|
27
|
+
|
28
|
+
* Strong parameters should permit nested number as key.
|
29
|
+
|
30
|
+
Fixes #12293.
|
31
|
+
|
32
|
+
*kennyj*
|
33
|
+
|
34
|
+
* Fix `collection_check_boxes` generated hidden input to use the name attribute provided
|
35
|
+
in the options hash.
|
36
|
+
|
37
|
+
*Angel N. Sciortino*
|
38
|
+
|
39
|
+
* Fix some edge cases for AV `select` helper with `:selected` option
|
40
|
+
|
41
|
+
*Bogdan Gusiev*
|
42
|
+
|
43
|
+
* Handle `:namespace` form option in collection labels
|
44
|
+
|
45
|
+
*Vasiliy Ermolovich*
|
46
|
+
|
47
|
+
* Fix an issue where router can't recognize downcased url encoding path.
|
48
|
+
|
49
|
+
Fixes #12269.
|
50
|
+
|
51
|
+
*kennyj*
|
52
|
+
|
53
|
+
* Fix custom flash type definition. Misusage of the `_flash_types` class variable
|
54
|
+
caused an error when reloading controllers with custom flash types.
|
55
|
+
|
56
|
+
Fixes #12057.
|
57
|
+
|
58
|
+
*Ricardo de Cillo*
|
59
|
+
|
60
|
+
* Do not break params filtering on `nil` values.
|
61
|
+
|
62
|
+
Fixes #12149.
|
63
|
+
|
64
|
+
*Vasiliy Ermolovich*
|
65
|
+
|
66
|
+
* Fix `excerpt` when `:separator` is `nil`.
|
67
|
+
|
68
|
+
*Paul Nikitochkin*
|
69
|
+
|
70
|
+
* Make Live Streaming work with basic authentication or builder.
|
71
|
+
|
72
|
+
Fixes #10984.
|
73
|
+
|
74
|
+
*Aaron Patterson*
|
75
|
+
|
76
|
+
* Always use `Rack::Sendfile` to make possible to it be automatically
|
77
|
+
configured by the webserver.
|
78
|
+
|
79
|
+
Fixes #11440.
|
80
|
+
|
81
|
+
*Martin Schürrer*
|
82
|
+
|
83
|
+
* Flag cookies as secure with ignore case in `ActionDispatch::SSL`.
|
84
|
+
|
85
|
+
*Yamagishi Kazutoshi*
|
86
|
+
|
87
|
+
* Don't include STS header in non-HTTPS responses.
|
88
|
+
|
89
|
+
*Geoff Buesing*
|
90
|
+
|
91
|
+
* Fix an issue where rails raise exception about missing helper where it
|
92
|
+
should throw `LoadError`. When helper file exists and only loaded file from
|
93
|
+
this helper does not exist rails should throw LoadError instead of
|
94
|
+
`MissingHelperError`.
|
95
|
+
|
96
|
+
*Piotr Niełacny*
|
97
|
+
|
98
|
+
* Only cache template digests if `config.cache_template_loading` is true.
|
99
|
+
|
100
|
+
*Josh Lauer*, *Justin Ridgewell*
|
101
|
+
|
102
|
+
* Fix an issue where `:if` and `:unless` controller action procs were being run
|
103
|
+
before checking for the correct action in the `:only` and `:unless` options.
|
104
|
+
|
105
|
+
Fixes #11799.
|
106
|
+
|
107
|
+
*Nicholas Jakobsen*
|
108
|
+
|
109
|
+
* Fix an issue where `assert_dom_equal` and `assert_dom_not_equal` were
|
110
|
+
ignoring the passed failure message argument.
|
111
|
+
|
112
|
+
Fixes #11751.
|
113
|
+
|
114
|
+
*Ryan McGeary*
|
115
|
+
|
116
|
+
* Fix `current_page?` when the URL contains escaped characters and the
|
117
|
+
original URL is using the hexadecimal lowercased.
|
118
|
+
|
119
|
+
*Rafael Mendonça França*
|
120
|
+
|
121
|
+
* Allow `REMOTE_ADDR`, `HTTP_HOST` and `HTTP_USER_AGENT` to be overridden from
|
122
|
+
the environment passed into `ActionDispatch::TestRequest.new`.
|
123
|
+
|
124
|
+
Fixes #11590.
|
125
|
+
|
126
|
+
*Andrew White*
|
127
|
+
|
128
|
+
* Fix `text_area` to behave like `text_field` when `nil` is given as
|
129
|
+
value.
|
130
|
+
|
131
|
+
Before:
|
132
|
+
|
133
|
+
f.text_field :field, value: nil #=> <input value="">
|
134
|
+
f.text_area :field, value: nil #=> <textarea>value of field</textarea>
|
135
|
+
|
136
|
+
After:
|
137
|
+
|
138
|
+
f.text_area :field, value: nil #=> <textarea></textarea>
|
139
|
+
|
140
|
+
*Joel Cogen*
|
141
|
+
|
142
|
+
* Fix an issue where Journey was failing to clear the named routes hash when the
|
143
|
+
routes were reloaded and since it doesn't overwrite existing routes then if a
|
144
|
+
route changed but wasn't renamed it kept the old definition. This was being
|
145
|
+
masked by the optimised url helpers so it only became apparent when passing an
|
146
|
+
options hash to the url helper.
|
147
|
+
|
148
|
+
*Andrew White*
|
149
|
+
|
150
|
+
* Skip routes pointing to a redirect or mounted application when generating urls
|
151
|
+
using an options hash as they aren't relevant and generate incorrect urls.
|
152
|
+
|
153
|
+
Fixes #8018.
|
154
|
+
|
155
|
+
*Andrew White*
|
156
|
+
|
157
|
+
* Fix default rendered format problem when calling `render` without `:content_type` option.
|
158
|
+
It should return `:html`.
|
159
|
+
|
160
|
+
Fixes #11393.
|
161
|
+
|
162
|
+
*Gleb Mazovetskiy*, *Oleg*, *kennyj*
|
163
|
+
|
164
|
+
* Fix `ActionDispatch::ParamsParser#parse_formatted_parameters` to rewind body input stream on
|
165
|
+
parsing json params.
|
166
|
+
|
167
|
+
Fixes #11345.
|
168
|
+
|
169
|
+
*Yuri Bol*, *Paul Nikitochkin*
|
170
|
+
|
171
|
+
* Fix `link_to` with block and url hashes.
|
172
|
+
|
173
|
+
Before:
|
174
|
+
|
175
|
+
link_to(action: 'bar', controller: 'foo') { content_tag(:span, 'Example site') }
|
176
|
+
# => "<a action=\"bar\" controller=\"foo\"><span>Example site</span></a>"
|
177
|
+
|
178
|
+
After:
|
179
|
+
|
180
|
+
link_to(action: 'bar', controller: 'foo') { content_tag(:span, 'Example site') }
|
181
|
+
# => "<a href=\"/foo/bar\"><span>Example site</span></a>"
|
182
|
+
|
183
|
+
*Murahashi Sanemat Kenichi*
|
184
|
+
|
185
|
+
* Fix "Stack Level Too Deep" error when redering recursive partials.
|
186
|
+
|
187
|
+
Fixes #11340.
|
188
|
+
|
189
|
+
*Rafael Mendonça França*
|
190
|
+
|
191
|
+
* Pick `DateField` `DateTimeField` and `ColorField` values from stringified options allowing use of symbol keys with helpers.
|
192
|
+
|
193
|
+
*Jon Rowe*
|
194
|
+
|
195
|
+
* Fix `Mime::Type.parse` when bad accepts header is looked up. Previously it
|
196
|
+
was setting `request.formats` with an array containing a `nil` value, which
|
197
|
+
raised an error when setting the controller formats.
|
198
|
+
|
199
|
+
Fixes #10965.
|
200
|
+
|
201
|
+
*Becker*
|
202
|
+
|
203
|
+
* Always escape the result of `link_to_unless` method.
|
204
|
+
|
205
|
+
Before:
|
206
|
+
|
207
|
+
link_to_unless(true, '<b>Showing</b>', 'github.com')
|
208
|
+
# => "<b>Showing</b>"
|
209
|
+
|
210
|
+
After:
|
211
|
+
|
212
|
+
link_to_unless(true, '<b>Showing</b>', 'github.com')
|
213
|
+
# => "<b>Showing</b>"
|
214
|
+
|
215
|
+
*dtaniwaki*
|
216
|
+
|
217
|
+
|
1
218
|
## Rails 4.0.0 (June 25, 2013) ##
|
2
219
|
|
3
220
|
* Merge `:action` from routing scope and assign endpoint if both `:controller`
|
@@ -30,6 +247,10 @@
|
|
30
247
|
|
31
248
|
*David Celis*
|
32
249
|
|
250
|
+
* Add `has_named_route?(route_name)` to the mapper API.
|
251
|
+
|
252
|
+
*José Valim*
|
253
|
+
|
33
254
|
* Fix an issue where partials with a number in the filename weren't being digested for cache dependencies.
|
34
255
|
|
35
256
|
*Bryan Ricker*
|
data/README.rdoc
CHANGED
@@ -37,7 +37,7 @@ The latest version of Action Pack can be installed with RubyGems:
|
|
37
37
|
|
38
38
|
Source code can be downloaded as part of the Rails project on GitHub
|
39
39
|
|
40
|
-
* https://github.com/rails/rails/tree/
|
40
|
+
* https://github.com/rails/rails/tree/4-0-stable/actionpack
|
41
41
|
|
42
42
|
|
43
43
|
== License
|
@@ -36,7 +36,7 @@ module AbstractController
|
|
36
36
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
37
37
|
if from = options[from]
|
38
38
|
from = Array(from).map {|o| "action_name == '#{o}'"}.join(" || ")
|
39
|
-
options[to] = Array(options[to])
|
39
|
+
options[to] = Array(options[to]).unshift(from)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -150,7 +150,12 @@ module AbstractController
|
|
150
150
|
@error = error
|
151
151
|
@path = "helpers/#{path}.rb"
|
152
152
|
set_backtrace error.backtrace
|
153
|
-
|
153
|
+
|
154
|
+
if error.path =~ /^#{path}(\.rb)?$/
|
155
|
+
super("Missing helper file helpers/%s.rb" % path)
|
156
|
+
else
|
157
|
+
raise error
|
158
|
+
end
|
154
159
|
end
|
155
160
|
end
|
156
161
|
|
@@ -59,7 +59,7 @@ module ActionController
|
|
59
59
|
# <input type="text" name="post[address]" value="hyacintvej">
|
60
60
|
#
|
61
61
|
# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
|
62
|
-
# If the address input had been named
|
62
|
+
# If the address input had been named <tt>post[address][street]</tt>, the params would have included
|
63
63
|
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
|
64
64
|
#
|
65
65
|
# == Sessions
|
@@ -201,6 +201,7 @@ module ActionController
|
|
201
201
|
# You may declare that the parameter should be an array of permitted scalars
|
202
202
|
# by mapping it to an empty array:
|
203
203
|
#
|
204
|
+
# params = ActionController::Parameters.new(tags: ['rails', 'parameters'])
|
204
205
|
# params.permit(tags: [])
|
205
206
|
#
|
206
207
|
# You can also use +permit+ on nested parameters, like:
|
@@ -328,7 +329,7 @@ module ActionController
|
|
328
329
|
def each_element(object)
|
329
330
|
if object.is_a?(Array)
|
330
331
|
object.map { |el| yield el }.compact
|
331
|
-
elsif
|
332
|
+
elsif fields_for_style?(object)
|
332
333
|
hash = object.class.new
|
333
334
|
object.each { |k,v| hash[k] = yield v }
|
334
335
|
hash
|
@@ -337,6 +338,10 @@ module ActionController
|
|
337
338
|
end
|
338
339
|
end
|
339
340
|
|
341
|
+
def fields_for_style?(object)
|
342
|
+
object.is_a?(Hash) && object.all? { |k, v| k =~ /\A-?\d+\z/ && v.is_a?(Hash) }
|
343
|
+
end
|
344
|
+
|
340
345
|
def unpermitted_parameters!(params)
|
341
346
|
unpermitted_keys = unpermitted_keys(params)
|
342
347
|
if unpermitted_keys.any?
|
@@ -415,7 +420,7 @@ module ActionController
|
|
415
420
|
|
416
421
|
# Slicing filters out non-declared keys.
|
417
422
|
slice(*filter.keys).each do |key, value|
|
418
|
-
|
423
|
+
next unless value
|
419
424
|
|
420
425
|
if filter[key] == EMPTY_ARRAY
|
421
426
|
# Declaration { comment_ids: [] }.
|
@@ -552,7 +552,7 @@ module ActionController
|
|
552
552
|
parameters ||= {}
|
553
553
|
controller_class_name = @controller.class.anonymous? ?
|
554
554
|
"anonymous" :
|
555
|
-
@controller.class.
|
555
|
+
@controller.class.controller_path
|
556
556
|
|
557
557
|
@request.assign_parameters(@routes, controller_class_name, action.to_s, parameters)
|
558
558
|
|
@@ -179,7 +179,7 @@ module Mime
|
|
179
179
|
def parse(accept_header)
|
180
180
|
if accept_header !~ /,/
|
181
181
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
182
|
-
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)]
|
182
|
+
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
183
183
|
else
|
184
184
|
list, index = AcceptList.new, 0
|
185
185
|
accept_header.split(',').each do |header|
|
@@ -198,7 +198,9 @@ module ActionDispatch # :nodoc:
|
|
198
198
|
if body.respond_to?(:to_path)
|
199
199
|
@stream = body
|
200
200
|
else
|
201
|
-
|
201
|
+
synchronize do
|
202
|
+
@stream = build_buffer self, munge_body_object(body)
|
203
|
+
end
|
202
204
|
end
|
203
205
|
end
|
204
206
|
|
@@ -18,7 +18,11 @@ module ActionDispatch
|
|
18
18
|
|
19
19
|
match_route(name, constraints) do |route|
|
20
20
|
parameterized_parts = extract_parameterized_parts(route, options, recall, parameterize)
|
21
|
-
|
21
|
+
|
22
|
+
# Skip this route unless a name has been provided or it is a
|
23
|
+
# standard Rails route since we can't determine whether an options
|
24
|
+
# hash passed to url_for matches a Rack application or a redirect.
|
25
|
+
next unless name || route.dispatcher?
|
22
26
|
|
23
27
|
missing_keys = missing_keys(route, parameterized_parts)
|
24
28
|
next unless missing_keys.empty?
|
@@ -9,8 +9,8 @@ module ActionDispatch
|
|
9
9
|
attr_reader :memos
|
10
10
|
|
11
11
|
def initialize
|
12
|
-
@regexp_states =
|
13
|
-
@string_states =
|
12
|
+
@regexp_states = {}
|
13
|
+
@string_states = {}
|
14
14
|
@accepting = {}
|
15
15
|
@memos = Hash.new { |h,k| h[k] = [] }
|
16
16
|
end
|
@@ -111,14 +111,8 @@ module ActionDispatch
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def []=(from, to, sym)
|
114
|
-
|
115
|
-
|
116
|
-
@string_states[from][sym] = to
|
117
|
-
when Regexp
|
118
|
-
@regexp_states[from][sym] = to
|
119
|
-
else
|
120
|
-
raise ArgumentError, 'unknown symbol: %s' % sym.class
|
121
|
-
end
|
114
|
+
to_mappings = states_hash_for(sym)[from] ||= {}
|
115
|
+
to_mappings[sym] = to
|
122
116
|
end
|
123
117
|
|
124
118
|
def states
|
@@ -137,18 +131,35 @@ module ActionDispatch
|
|
137
131
|
|
138
132
|
private
|
139
133
|
|
134
|
+
def states_hash_for(sym)
|
135
|
+
case sym
|
136
|
+
when String
|
137
|
+
@string_states
|
138
|
+
when Regexp
|
139
|
+
@regexp_states
|
140
|
+
else
|
141
|
+
raise ArgumentError, 'unknown symbol: %s' % sym.class
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
140
145
|
def move_regexp(t, a)
|
141
146
|
return [] if t.empty?
|
142
147
|
|
143
148
|
t.map { |s|
|
144
|
-
@regexp_states[s]
|
149
|
+
if states = @regexp_states[s]
|
150
|
+
states.map { |re, v| re === a ? v : nil }
|
151
|
+
end
|
145
152
|
}.flatten.compact.uniq
|
146
153
|
end
|
147
154
|
|
148
155
|
def move_string(t, a)
|
149
156
|
return [] if t.empty?
|
150
157
|
|
151
|
-
t.map
|
158
|
+
t.map do |s|
|
159
|
+
if states = @string_states[s]
|
160
|
+
states[a]
|
161
|
+
end
|
162
|
+
end.compact
|
152
163
|
end
|
153
164
|
end
|
154
165
|
end
|
@@ -16,6 +16,14 @@ module ActionDispatch
|
|
16
16
|
@app = app
|
17
17
|
@path = path
|
18
18
|
|
19
|
+
# Unwrap any constraints so we can see what's inside for route generation.
|
20
|
+
# This allows the formatter to skip over any mounted applications or redirects
|
21
|
+
# that shouldn't be matched when using a url_for without a route name.
|
22
|
+
while app.is_a?(Routing::Mapper::Constraints) do
|
23
|
+
app = app.app
|
24
|
+
end
|
25
|
+
@dispatcher = app.is_a?(Routing::RouteSet::Dispatcher)
|
26
|
+
|
19
27
|
@constraints = constraints
|
20
28
|
@defaults = defaults
|
21
29
|
@required_defaults = nil
|
@@ -93,6 +101,10 @@ module ActionDispatch
|
|
93
101
|
end
|
94
102
|
end
|
95
103
|
|
104
|
+
def dispatcher?
|
105
|
+
@dispatcher
|
106
|
+
end
|
107
|
+
|
96
108
|
def matches?(request)
|
97
109
|
constraints.all? do |method, value|
|
98
110
|
next true unless request.respond_to?(method)
|
@@ -7,15 +7,18 @@ module ActionDispatch
|
|
7
7
|
# Normalizes URI path.
|
8
8
|
#
|
9
9
|
# Strips off trailing slash and ensures there is a leading slash.
|
10
|
+
# Also converts downcase url encoded string to uppercase.
|
10
11
|
#
|
11
12
|
# normalize_path("/foo") # => "/foo"
|
12
13
|
# normalize_path("/foo/") # => "/foo"
|
13
14
|
# normalize_path("foo") # => "/foo"
|
14
15
|
# normalize_path("") # => "/"
|
16
|
+
# normalize_path("/%ab") # => "/%AB"
|
15
17
|
def self.normalize_path(path)
|
16
18
|
path = "/#{path}"
|
17
19
|
path.squeeze!('/')
|
18
20
|
path.sub!(%r{/+\Z}, '')
|
21
|
+
path.gsub!(/(%[a-f0-9]{2}+)/) { $1.upcase }
|
19
22
|
path = '/' if path == ''
|
20
23
|
path
|
21
24
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thread_safe'
|
4
|
+
|
2
5
|
module ActionDispatch
|
3
6
|
module Journey # :nodoc:
|
4
7
|
module Visitors # :nodoc:
|
5
8
|
class Visitor # :nodoc:
|
6
|
-
DISPATCH_CACHE =
|
7
|
-
h[k] = "visit_#{k}"
|
9
|
+
DISPATCH_CACHE = ThreadSafe::Cache.new { |h,k|
|
10
|
+
h[k] = :"visit_#{k}"
|
8
11
|
}
|
9
12
|
|
10
13
|
def accept(node)
|
@@ -160,7 +160,7 @@ module ActionDispatch
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
# Returns the +signed+ or +encrypted jar, preferring +encrypted+ if +secret_key_base+ is set.
|
163
|
+
# Returns the +signed+ or +encrypted+ jar, preferring +encrypted+ if +secret_key_base+ is set.
|
164
164
|
# Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores.
|
165
165
|
def signed_or_encrypted
|
166
166
|
@signed_or_encrypted ||=
|
@@ -41,7 +41,7 @@ module ActionDispatch
|
|
41
41
|
when Proc
|
42
42
|
strategy.call(request.raw_post)
|
43
43
|
when :json
|
44
|
-
data = ActiveSupport::JSON.decode(request.
|
44
|
+
data = ActiveSupport::JSON.decode(request.raw_post)
|
45
45
|
data = {:_json => data} unless data.is_a?(Hash)
|
46
46
|
request.deep_munge(data).with_indifferent_access
|
47
47
|
else
|
@@ -143,7 +143,7 @@ module ActionDispatch
|
|
143
143
|
# proxies with incompatible IP header conventions, and there is no way
|
144
144
|
# for us to determine which header is the right one after the fact.
|
145
145
|
# Since we have no idea, we give up and explode.
|
146
|
-
should_check_ip = @check_ip && client_ips.last
|
146
|
+
should_check_ip = @check_ip && client_ips.last && forwarded_ips.last
|
147
147
|
if should_check_ip && !forwarded_ips.include?(client_ips.last)
|
148
148
|
# We don't know which came from the proxy, and which from the user
|
149
149
|
raise IpSpoofAttackError, "IP spoofing attack?! " +
|
@@ -36,8 +36,7 @@ module ActionDispatch
|
|
36
36
|
url.scheme = "https"
|
37
37
|
url.host = @host if @host
|
38
38
|
url.port = @port if @port
|
39
|
-
headers =
|
40
|
-
'Location' => url.to_s)
|
39
|
+
headers = { 'Content-Type' => 'text/html', 'Location' => url.to_s }
|
41
40
|
|
42
41
|
[301, headers, []]
|
43
42
|
end
|
@@ -58,7 +57,7 @@ module ActionDispatch
|
|
58
57
|
cookies = cookies.split("\n")
|
59
58
|
|
60
59
|
headers['Set-Cookie'] = cookies.map { |cookie|
|
61
|
-
if cookie !~ /;\s+secure(;|$)/
|
60
|
+
if cookie !~ /;\s+secure(;|$)/i
|
62
61
|
"#{cookie}; secure"
|
63
62
|
else
|
64
63
|
cookie
|
@@ -515,6 +515,11 @@ module ActionDispatch
|
|
515
515
|
end
|
516
516
|
end
|
517
517
|
|
518
|
+
# Query if the following named route was already defined.
|
519
|
+
def has_named_route?(name)
|
520
|
+
@set.named_routes.routes[name.to_sym]
|
521
|
+
end
|
522
|
+
|
518
523
|
private
|
519
524
|
def app_name(app)
|
520
525
|
return unless app.respond_to?(:routes)
|
@@ -30,6 +30,10 @@ module ActionDispatch
|
|
30
30
|
uri.host ||= req.host
|
31
31
|
uri.port ||= req.port unless req.standard_port?
|
32
32
|
|
33
|
+
if relative_path?(uri.path)
|
34
|
+
uri.path = "#{req.script_name}/#{uri.path}"
|
35
|
+
end
|
36
|
+
|
33
37
|
body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
|
34
38
|
|
35
39
|
headers = {
|
@@ -48,6 +52,11 @@ module ActionDispatch
|
|
48
52
|
def inspect
|
49
53
|
"redirect(#{status})"
|
50
54
|
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def relative_path?(path)
|
58
|
+
path && !path.empty? && path[0] != '/'
|
59
|
+
end
|
51
60
|
end
|
52
61
|
|
53
62
|
class PathRedirect < Redirect
|
@@ -81,6 +90,11 @@ module ActionDispatch
|
|
81
90
|
url_options[:path] = (url_options[:path] % escape_path(params))
|
82
91
|
end
|
83
92
|
|
93
|
+
if relative_path?(url_options[:path])
|
94
|
+
url_options[:path] = "/#{url_options[:path]}"
|
95
|
+
url_options[:script_name] = request.script_name
|
96
|
+
end
|
97
|
+
|
84
98
|
ActionDispatch::Http::URL.url_for url_options
|
85
99
|
end
|
86
100
|
|
@@ -104,6 +118,10 @@ module ActionDispatch
|
|
104
118
|
#
|
105
119
|
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
106
120
|
#
|
121
|
+
# Note that if you return a path without a leading slash then the url is prefixed with the
|
122
|
+
# current SCRIPT_NAME environment variable. This is typically '/' but may be different in
|
123
|
+
# a mounted engine or where the application is deployed to a subdirectory of a website.
|
124
|
+
#
|
107
125
|
# Alternatively you can use one of the other syntaxes:
|
108
126
|
#
|
109
127
|
# The block version of redirect allows for the easy encapsulation of any logic associated with
|
@@ -186,10 +186,16 @@ module ActionDispatch
|
|
186
186
|
klass = Journey::Router::Utils
|
187
187
|
|
188
188
|
@path_parts.zip(args) do |part, arg|
|
189
|
+
parameterized_arg = arg.to_param
|
190
|
+
|
191
|
+
if parameterized_arg.nil? || parameterized_arg.empty?
|
192
|
+
raise_generation_error(args)
|
193
|
+
end
|
194
|
+
|
189
195
|
# Replace each route parameter
|
190
196
|
# e.g. :id for regular parameter or *path for globbing
|
191
197
|
# with ruby string interpolation code
|
192
|
-
path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(
|
198
|
+
path.gsub!(/(\*|:)#{part}/, klass.escape_fragment(parameterized_arg))
|
193
199
|
end
|
194
200
|
path
|
195
201
|
end
|
@@ -197,6 +203,25 @@ module ActionDispatch
|
|
197
203
|
def optimize_routes_generation?(t)
|
198
204
|
t.send(:optimize_routes_generation?)
|
199
205
|
end
|
206
|
+
|
207
|
+
def raise_generation_error(args)
|
208
|
+
parts, missing_keys = [], []
|
209
|
+
|
210
|
+
@path_parts.zip(args) do |part, arg|
|
211
|
+
parameterized_arg = arg.to_param
|
212
|
+
|
213
|
+
if parameterized_arg.nil? || parameterized_arg.empty?
|
214
|
+
missing_keys << part
|
215
|
+
end
|
216
|
+
|
217
|
+
parts << [part, arg]
|
218
|
+
end
|
219
|
+
|
220
|
+
message = "No route matches #{Hash[parts].inspect}"
|
221
|
+
message << " missing required keys: #{missing_keys.inspect}"
|
222
|
+
|
223
|
+
raise ActionController::UrlGenerationError, message
|
224
|
+
end
|
200
225
|
end
|
201
226
|
|
202
227
|
def initialize(route, options)
|
@@ -7,20 +7,20 @@ module ActionDispatch
|
|
7
7
|
#
|
8
8
|
# # assert that the referenced method generates the appropriate HTML string
|
9
9
|
# assert_dom_equal '<a href="http://www.example.com">Apples</a>', link_to("Apples", "http://www.example.com")
|
10
|
-
def assert_dom_equal(expected, actual, message =
|
10
|
+
def assert_dom_equal(expected, actual, message = nil)
|
11
11
|
expected_dom = HTML::Document.new(expected).root
|
12
12
|
actual_dom = HTML::Document.new(actual).root
|
13
|
-
assert_equal expected_dom, actual_dom
|
13
|
+
assert_equal expected_dom, actual_dom, message
|
14
14
|
end
|
15
15
|
|
16
16
|
# The negated form of +assert_dom_equivalent+.
|
17
17
|
#
|
18
18
|
# # assert that the referenced method does not generate the specified HTML string
|
19
19
|
# assert_dom_not_equal '<a href="http://www.example.com">Apples</a>', link_to("Oranges", "http://www.example.com")
|
20
|
-
def assert_dom_not_equal(expected, actual, message =
|
20
|
+
def assert_dom_not_equal(expected, actual, message = nil)
|
21
21
|
expected_dom = HTML::Document.new(expected).root
|
22
22
|
actual_dom = HTML::Document.new(actual).root
|
23
|
-
assert_not_equal expected_dom, actual_dom
|
23
|
+
assert_not_equal expected_dom, actual_dom, message
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -3,7 +3,11 @@ require 'rack/utils'
|
|
3
3
|
|
4
4
|
module ActionDispatch
|
5
5
|
class TestRequest < Request
|
6
|
-
DEFAULT_ENV = Rack::MockRequest.env_for('/'
|
6
|
+
DEFAULT_ENV = Rack::MockRequest.env_for('/',
|
7
|
+
'HTTP_HOST' => 'test.host',
|
8
|
+
'REMOTE_ADDR' => '0.0.0.0',
|
9
|
+
'HTTP_USER_AGENT' => 'Rails Testing'
|
10
|
+
)
|
7
11
|
|
8
12
|
def self.new(env = {})
|
9
13
|
super
|
@@ -12,10 +16,6 @@ module ActionDispatch
|
|
12
16
|
def initialize(env = {})
|
13
17
|
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
|
14
18
|
super(default_env.merge(env))
|
15
|
-
|
16
|
-
self.host = 'test.host'
|
17
|
-
self.remote_addr = '0.0.0.0'
|
18
|
-
self.user_agent = 'Rails Testing'
|
19
19
|
end
|
20
20
|
|
21
21
|
def request_method=(method)
|
data/lib/action_pack/version.rb
CHANGED
@@ -74,7 +74,7 @@ module ActionView
|
|
74
74
|
# render(@topic) => render("topics/topic")
|
75
75
|
# render(topics) => render("topics/topic")
|
76
76
|
# render(message.topics) => render("topics/topic")
|
77
|
-
collect { |name| name.sub(/\A@?([a-
|
77
|
+
collect { |name| name.sub(/\A@?([a-z_]+\.)*([a-z_]+)\z/) { "#{$2.pluralize}/#{$2.singularize}" } }.
|
78
78
|
|
79
79
|
# render("headline") => render("message/headline")
|
80
80
|
collect { |name| name.include?("/") ? name : "#{directory}/#{name}" }.
|
data/lib/action_view/digestor.rb
CHANGED
@@ -1,16 +1,44 @@
|
|
1
1
|
require 'thread_safe'
|
2
2
|
require 'action_view/dependency_tracker'
|
3
|
+
require 'monitor'
|
3
4
|
|
4
5
|
module ActionView
|
5
6
|
class Digestor
|
6
7
|
cattr_reader(:cache)
|
7
|
-
@@cache
|
8
|
+
@@cache = ThreadSafe::Cache.new
|
9
|
+
@@digest_monitor = Monitor.new
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def digest(name, format, finder, options = {})
|
13
|
+
cache_key = ([name, format] + Array.wrap(options[:dependencies])).join('.')
|
14
|
+
# this is a correctly done double-checked locking idiom
|
15
|
+
# (ThreadSafe::Cache's lookups have volatile semantics)
|
16
|
+
@@cache[cache_key] || @@digest_monitor.synchronize do
|
17
|
+
@@cache.fetch(cache_key) do # re-check under lock
|
18
|
+
compute_and_store_digest(cache_key, name, format, finder, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def compute_and_store_digest(cache_key, name, format, finder, options) # called under @@digest_monitor lock
|
25
|
+
klass = if options[:partial] || name.include?("/_")
|
26
|
+
# Prevent re-entry or else recursive templates will blow the stack.
|
27
|
+
# There is no need to worry about other threads seeing the +false+ value,
|
28
|
+
# as they will then have to wait for this thread to let go of the @@digest_monitor lock.
|
29
|
+
pre_stored = @@cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
|
30
|
+
PartialDigestor
|
31
|
+
else
|
32
|
+
Digestor
|
33
|
+
end
|
8
34
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
35
|
+
digest = klass.new(name, format, finder, options).digest
|
36
|
+
# Store the actual digest if config.cache_template_loading is true
|
37
|
+
@@cache[cache_key] = stored_digest = digest if ActionView::Resolver.caching?
|
38
|
+
digest
|
39
|
+
ensure
|
40
|
+
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
|
41
|
+
@@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
|
14
42
|
end
|
15
43
|
end
|
16
44
|
|
@@ -539,7 +539,7 @@ module ActionView
|
|
539
539
|
# my_date = Time.now + 2.days
|
540
540
|
#
|
541
541
|
# # Generates a select field for days that defaults to the day for the date in my_date.
|
542
|
-
# select_day(
|
542
|
+
# select_day(my_date)
|
543
543
|
#
|
544
544
|
# # Generates a select field for days that defaults to the number given.
|
545
545
|
# select_day(5)
|
@@ -549,7 +549,7 @@ module ActionView
|
|
549
549
|
#
|
550
550
|
# # Generates a select field for days that defaults to the day for the date in my_date
|
551
551
|
# # that is named 'due' rather than 'day'.
|
552
|
-
# select_day(
|
552
|
+
# select_day(my_date, field_name: 'due')
|
553
553
|
#
|
554
554
|
# # Generates a select field for days with a custom prompt. Use <tt>prompt: true</tt> for a
|
555
555
|
# # generic prompt.
|
@@ -1172,7 +1172,7 @@ module ActionView
|
|
1172
1172
|
# methods in the +FormHelper+ module. This class, however, allows you to
|
1173
1173
|
# call methods with the model object you are building the form for.
|
1174
1174
|
#
|
1175
|
-
# You can create your own custom FormBuilder templates by
|
1175
|
+
# You can create your own custom FormBuilder templates by subclassing this
|
1176
1176
|
# class. For example:
|
1177
1177
|
#
|
1178
1178
|
# class MyFormBuilder < ActionView::Helpers::FormBuilder
|
@@ -97,14 +97,17 @@ module ActionView
|
|
97
97
|
# Create a select tag and a series of contained option tags for the provided object and method.
|
98
98
|
# The option currently held by the object will be selected, provided that the object is available.
|
99
99
|
#
|
100
|
-
# There are two possible formats for the choices parameter, corresponding to other helpers' output:
|
101
|
-
#
|
102
|
-
#
|
100
|
+
# There are two possible formats for the +choices+ parameter, corresponding to other helpers' output:
|
101
|
+
#
|
102
|
+
# * A flat collection (see +options_for_select+).
|
103
|
+
#
|
104
|
+
# * A nested collection (see +grouped_options_for_select+).
|
105
|
+
#
|
106
|
+
# For example:
|
103
107
|
#
|
104
|
-
# Example with @post.person_id => 1:
|
105
108
|
# select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })
|
106
109
|
#
|
107
|
-
#
|
110
|
+
# would become:
|
108
111
|
#
|
109
112
|
# <select name="post[person_id]">
|
110
113
|
# <option value=""></option>
|
@@ -113,6 +116,8 @@ module ActionView
|
|
113
116
|
# <option value="3">Tobias</option>
|
114
117
|
# </select>
|
115
118
|
#
|
119
|
+
# assuming the associated person has ID 1.
|
120
|
+
#
|
116
121
|
# This can be used to provide a default set of options in the standard way: before rendering the create form, a
|
117
122
|
# new model instance is assigned the default options and bound to @model_name. Usually this model is not saved
|
118
123
|
# to the database. Instead, a second model object is created when the create request is received.
|
@@ -654,7 +659,7 @@ module ActionView
|
|
654
659
|
#
|
655
660
|
# Example object structure for use with this method:
|
656
661
|
# class Post < ActiveRecord::Base
|
657
|
-
# has_and_belongs_to_many :
|
662
|
+
# has_and_belongs_to_many :authors
|
658
663
|
# end
|
659
664
|
# class Author < ActiveRecord::Base
|
660
665
|
# has_and_belongs_to_many :posts
|
@@ -119,7 +119,8 @@ module ActionView
|
|
119
119
|
html_options = html_options.stringify_keys
|
120
120
|
add_default_name_and_id(html_options)
|
121
121
|
options[:include_blank] ||= true unless options[:prompt] || select_not_required?(html_options)
|
122
|
-
|
122
|
+
value = options.fetch(:selected) { value(object) }
|
123
|
+
select = content_tag("select", add_options(option_tags, options, value), html_options)
|
123
124
|
|
124
125
|
if html_options["multiple"] && options.fetch(:include_hidden, true)
|
125
126
|
tag("input", :disabled => html_options["disabled"], :name => html_options["name"], :type => "hidden", :value => "") + select
|
@@ -27,7 +27,8 @@ module ActionView
|
|
27
27
|
|
28
28
|
# Append a hidden field to make sure something will be sent back to the
|
29
29
|
# server if all check boxes are unchecked.
|
30
|
-
|
30
|
+
hidden_name = @html_options[:name] || "#{tag_name}[]"
|
31
|
+
hidden = @template_object.hidden_field_tag(hidden_name, "", :id => nil)
|
31
32
|
|
32
33
|
rendered_collection + hidden
|
33
34
|
end
|
@@ -18,7 +18,8 @@ module ActionView
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def label(label_html_options={}, &block)
|
21
|
-
|
21
|
+
html_options = label_html_options.merge(@input_html_options)
|
22
|
+
@template_object.label(@object_name, @sanitized_attribute_name, @text, html_options, &block)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -4,7 +4,7 @@ module ActionView
|
|
4
4
|
class ColorField < TextField # :nodoc:
|
5
5
|
def render
|
6
6
|
options = @options.stringify_keys
|
7
|
-
options["value"] =
|
7
|
+
options["value"] = options.fetch("value") { validate_color_string(value(object)) }
|
8
8
|
@options = options
|
9
9
|
super
|
10
10
|
end
|
@@ -4,7 +4,7 @@ module ActionView
|
|
4
4
|
class DatetimeField < TextField # :nodoc:
|
5
5
|
def render
|
6
6
|
options = @options.stringify_keys
|
7
|
-
options["value"] =
|
7
|
+
options["value"] = options.fetch("value") { format_date(value(object)) }
|
8
8
|
options["min"] = format_date(options["min"])
|
9
9
|
options["max"] = format_date(options["max"])
|
10
10
|
@options = options
|
@@ -10,7 +10,7 @@ module ActionView
|
|
10
10
|
options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
|
11
11
|
end
|
12
12
|
|
13
|
-
content_tag("textarea", options.delete(
|
13
|
+
content_tag("textarea", options.delete("value") { value_before_type_cast(object) }, options)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -5,8 +5,8 @@ module ActionView
|
|
5
5
|
def render
|
6
6
|
options = @options.stringify_keys
|
7
7
|
options["size"] = options["maxlength"] unless options.key?("size")
|
8
|
-
options["type"]
|
9
|
-
options["value"] = options.fetch("value"){ value_before_type_cast(object) } unless field_type == "file"
|
8
|
+
options["type"] ||= field_type
|
9
|
+
options["value"] = options.fetch("value") { value_before_type_cast(object) } unless field_type == "file"
|
10
10
|
options["value"] &&= ERB::Util.html_escape(options["value"])
|
11
11
|
add_default_name_and_id(options)
|
12
12
|
tag("input", options)
|
@@ -150,7 +150,7 @@ module ActionView
|
|
150
150
|
def excerpt(text, phrase, options = {})
|
151
151
|
return unless text && phrase
|
152
152
|
|
153
|
-
separator = options
|
153
|
+
separator = options[:separator] || ''
|
154
154
|
phrase = Regexp.escape(phrase)
|
155
155
|
regex = /#{phrase}/i
|
156
156
|
|
@@ -169,7 +169,8 @@ module ActionView
|
|
169
169
|
prefix, first_part = cut_excerpt_part(:first, first_part, separator, options)
|
170
170
|
postfix, second_part = cut_excerpt_part(:second, second_part, separator, options)
|
171
171
|
|
172
|
-
|
172
|
+
affix = [first_part, separator, phrase, separator, second_part].join.strip
|
173
|
+
[prefix, affix, postfix].join
|
173
174
|
end
|
174
175
|
|
175
176
|
# Attempts to pluralize the +singular+ word unless +count+ is 1. If
|
@@ -172,7 +172,7 @@ module ActionView
|
|
172
172
|
# link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
|
173
173
|
# # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
|
174
174
|
def link_to(name = nil, options = nil, html_options = nil, &block)
|
175
|
-
html_options, options = options, name if block_given?
|
175
|
+
html_options, options, name = options, name, block if block_given?
|
176
176
|
options ||= {}
|
177
177
|
|
178
178
|
html_options = convert_options_to_data_attributes(options, html_options)
|
@@ -380,7 +380,7 @@ module ActionView
|
|
380
380
|
if block_given?
|
381
381
|
block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block)
|
382
382
|
else
|
383
|
-
name
|
383
|
+
ERB::Util.html_escape(name)
|
384
384
|
end
|
385
385
|
else
|
386
386
|
link_to(name, options, html_options)
|
@@ -528,12 +528,13 @@ module ActionView
|
|
528
528
|
|
529
529
|
return false unless request.get? || request.head?
|
530
530
|
|
531
|
-
url_string = url_for(options)
|
531
|
+
url_string = URI.parser.unescape(url_for(options)).force_encoding(Encoding::BINARY)
|
532
532
|
|
533
533
|
# We ignore any extra parameters in the request_uri if the
|
534
534
|
# submitted url doesn't have any either. This lets the function
|
535
535
|
# work with things like ?order=asc
|
536
536
|
request_uri = url_string.index("?") ? request.fullpath : request.path
|
537
|
+
request_uri = URI.parser.unescape(request_uri).force_encoding(Encoding::BINARY)
|
537
538
|
|
538
539
|
if url_string =~ /^\w+:\/\//
|
539
540
|
url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
|
data/lib/action_view/railtie.rb
CHANGED
@@ -11,7 +11,7 @@ module ActionView
|
|
11
11
|
prepend_formats(template.formats)
|
12
12
|
|
13
13
|
unless context.rendered_format
|
14
|
-
context.rendered_format = template.formats.first || formats.
|
14
|
+
context.rendered_format = template.formats.first || formats.first
|
15
15
|
end
|
16
16
|
|
17
17
|
render_template(template, options[:layout], options[:locals])
|
@@ -0,0 +1,17 @@
|
|
1
|
+
namespace :cache_digests do
|
2
|
+
desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
3
|
+
task :nested_dependencies => :environment do
|
4
|
+
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
5
|
+
template, format = ENV['TEMPLATE'].split(".")
|
6
|
+
format ||= :html
|
7
|
+
puts JSON.pretty_generate ActionView::Digestor.new(template, format, ApplicationController.new.lookup_context).nested_dependencies
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
11
|
+
task :dependencies => :environment do
|
12
|
+
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
13
|
+
template, format = ENV['TEMPLATE'].split(".")
|
14
|
+
format ||= :html
|
15
|
+
puts JSON.pretty_generate ActionView::Digestor.new(template, format, ApplicationController.new.lookup_context).dependencies
|
16
|
+
end
|
17
|
+
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.0.
|
4
|
+
version: 4.0.1.rc1
|
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: 2013-
|
11
|
+
date: 2013-10-17 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.0.
|
19
|
+
version: 4.0.1.rc1
|
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.0.
|
26
|
+
version: 4.0.1.rc1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: builder
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 4.0.
|
89
|
+
version: 4.0.1.rc1
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 4.0.
|
96
|
+
version: 4.0.1.rc1
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: tzinfo
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -340,6 +340,7 @@ files:
|
|
340
340
|
- lib/action_view/renderer/streaming_template_renderer.rb
|
341
341
|
- lib/action_view/renderer/template_renderer.rb
|
342
342
|
- lib/action_view/routing_url_for.rb
|
343
|
+
- lib/action_view/tasks/dependencies.rake
|
343
344
|
- lib/action_view/template/error.rb
|
344
345
|
- lib/action_view/template/handlers/builder.rb
|
345
346
|
- lib/action_view/template/handlers/erb.rb
|
@@ -374,13 +375,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
374
375
|
version: 1.9.3
|
375
376
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
376
377
|
requirements:
|
377
|
-
- - '
|
378
|
+
- - '>'
|
378
379
|
- !ruby/object:Gem::Version
|
379
|
-
version:
|
380
|
+
version: 1.3.1
|
380
381
|
requirements:
|
381
382
|
- none
|
382
383
|
rubyforge_project:
|
383
|
-
rubygems_version: 2.0.
|
384
|
+
rubygems_version: 2.0.6
|
384
385
|
signing_key:
|
385
386
|
specification_version: 4
|
386
387
|
summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
|