actionpack 3.2.8 → 3.2.9.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.
- data/CHANGELOG.md +107 -5654
- data/lib/abstract_controller/layouts.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +2 -1
- data/lib/action_controller/metal/data_streaming.rb +22 -2
- data/lib/action_controller/test_case.rb +41 -30
- data/lib/action_dispatch/http/upload.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +6 -4
- data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
- data/lib/action_dispatch/routing/mapper.rb +3 -3
- data/lib/action_dispatch/testing/integration.rb +3 -4
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +8 -7
- data/lib/action_view/helpers/date_helper.rb +5 -2
- data/lib/action_view/helpers/form_tag_helper.rb +1 -0
- data/lib/action_view/helpers/url_helper.rb +3 -1
- data/lib/action_view/test_case.rb +3 -3
- data/lib/sprockets/helpers/rails_helper.rb +3 -1
- data/lib/sprockets/static_compiler.rb +12 -20
- metadata +11 -14
@@ -309,7 +309,7 @@ module AbstractController
|
|
309
309
|
# still does a dynamic lookup. In next Rails release, we should @_layout
|
310
310
|
# to be inheritable so we can skip the child lookup if the parent explicitly
|
311
311
|
# set the layout.
|
312
|
-
parent = self.superclass.
|
312
|
+
parent = self.superclass.instance_eval { @_layout if defined?(@_layout) }
|
313
313
|
@_layout = nil
|
314
314
|
inspect = parent.is_a?(Proc) ? parent.inspect : parent
|
315
315
|
|
@@ -20,7 +20,8 @@ module ActionController
|
|
20
20
|
|
21
21
|
status = payload[:status]
|
22
22
|
if status.nil? && payload[:exception].present?
|
23
|
-
|
23
|
+
exception_class_name = payload[:exception].first
|
24
|
+
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
|
24
25
|
end
|
25
26
|
message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration
|
26
27
|
message << " (#{additions.join(" | ")})" unless additions.blank?
|
@@ -75,7 +75,27 @@ module ActionController #:nodoc:
|
|
75
75
|
|
76
76
|
self.status = options[:status] || 200
|
77
77
|
self.content_type = options[:content_type] if options.key?(:content_type)
|
78
|
-
self.response_body =
|
78
|
+
self.response_body = FileBody.new(path)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Avoid having to pass an open file handle as the response body.
|
82
|
+
# Rack::Sendfile will usually intercept the response and uses
|
83
|
+
# the path directly, so there is no reason to open the file.
|
84
|
+
class FileBody #:nodoc:
|
85
|
+
attr_reader :to_path
|
86
|
+
|
87
|
+
def initialize(path)
|
88
|
+
@to_path = path
|
89
|
+
end
|
90
|
+
|
91
|
+
# Stream the file's contents if Rack::Sendfile isn't present.
|
92
|
+
def each
|
93
|
+
File.open(to_path, 'rb') do |file|
|
94
|
+
while chunk = file.read(16384)
|
95
|
+
yield chunk
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
79
99
|
end
|
80
100
|
|
81
101
|
# Sends the given binary data to the browser. This method is similar to
|
@@ -115,7 +135,7 @@ module ActionController #:nodoc:
|
|
115
135
|
private
|
116
136
|
def send_file_headers!(options)
|
117
137
|
type_provided = options.has_key?(:type)
|
118
|
-
|
138
|
+
|
119
139
|
options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
|
120
140
|
[:type, :disposition].each do |arg|
|
121
141
|
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
|
@@ -14,13 +14,13 @@ module ActionController
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def setup_subscriptions
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
17
|
+
@_partials = Hash.new(0)
|
18
|
+
@_templates = Hash.new(0)
|
19
|
+
@_layouts = Hash.new(0)
|
20
20
|
|
21
21
|
ActiveSupport::Notifications.subscribe("render_template.action_view") do |name, start, finish, id, payload|
|
22
22
|
path = payload[:layout]
|
23
|
-
@
|
23
|
+
@_layouts[path] += 1
|
24
24
|
end
|
25
25
|
|
26
26
|
ActiveSupport::Notifications.subscribe("!render_template.action_view") do |name, start, finish, id, payload|
|
@@ -28,11 +28,11 @@ module ActionController
|
|
28
28
|
next unless path
|
29
29
|
partial = path =~ /^.*\/_[^\/]*$/
|
30
30
|
if partial
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
31
|
+
@_partials[path] += 1
|
32
|
+
@_partials[path.split("/").last] += 1
|
33
|
+
@_templates[path] += 1
|
34
34
|
else
|
35
|
-
@
|
35
|
+
@_templates[path] += 1
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -43,9 +43,9 @@ module ActionController
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def process(*args)
|
46
|
-
@
|
47
|
-
@
|
48
|
-
@
|
46
|
+
@_partials = Hash.new(0)
|
47
|
+
@_templates = Hash.new(0)
|
48
|
+
@_layouts = Hash.new(0)
|
49
49
|
super
|
50
50
|
end
|
51
51
|
|
@@ -72,43 +72,54 @@ module ActionController
|
|
72
72
|
validate_request!
|
73
73
|
|
74
74
|
case options
|
75
|
-
when NilClass, String, Symbol
|
75
|
+
when NilClass, Regexp, String, Symbol
|
76
76
|
options = options.to_s if Symbol === options
|
77
|
-
rendered = @
|
77
|
+
rendered = @_templates
|
78
78
|
msg = build_message(message,
|
79
79
|
"expecting <?> but rendering with <?>",
|
80
80
|
options, rendered.keys.join(', '))
|
81
|
-
|
82
|
-
|
81
|
+
matches_template =
|
82
|
+
case options
|
83
|
+
when String
|
84
|
+
rendered.any? do |t, num|
|
85
|
+
options_splited = options.split(File::SEPARATOR)
|
86
|
+
t_splited = t.split(File::SEPARATOR)
|
87
|
+
t_splited.last(options_splited.size) == options_splited
|
88
|
+
end
|
89
|
+
when Regexp
|
83
90
|
rendered.any? { |t,num| t.match(options) }
|
84
|
-
|
85
|
-
|
91
|
+
when NilClass
|
92
|
+
rendered.blank?
|
86
93
|
end
|
87
|
-
|
94
|
+
assert matches_template, msg
|
88
95
|
when Hash
|
89
96
|
if expected_layout = options[:layout]
|
90
97
|
msg = build_message(message,
|
91
98
|
"expecting layout <?> but action rendered <?>",
|
92
|
-
expected_layout, @
|
99
|
+
expected_layout, @_layouts.keys)
|
93
100
|
|
94
101
|
case expected_layout
|
95
102
|
when String
|
96
|
-
assert(@
|
103
|
+
assert(@_layouts.keys.include?(expected_layout), msg)
|
97
104
|
when Regexp
|
98
|
-
assert(@
|
105
|
+
assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg)
|
99
106
|
when nil
|
100
|
-
assert(@
|
107
|
+
assert(@_layouts.empty?, msg)
|
101
108
|
end
|
102
109
|
end
|
103
110
|
|
104
111
|
if expected_partial = options[:partial]
|
105
112
|
if expected_locals = options[:locals]
|
106
|
-
|
107
|
-
|
108
|
-
|
113
|
+
if defined?(@locals)
|
114
|
+
actual_locals = @locals[expected_partial.to_s.sub(/^_/,'')]
|
115
|
+
expected_locals.each_pair do |k,v|
|
116
|
+
assert_equal(v, actual_locals[k])
|
117
|
+
end
|
118
|
+
else
|
119
|
+
warn "the :locals option to #assert_template is only supported in a ActionView::TestCase"
|
109
120
|
end
|
110
121
|
elsif expected_count = options[:count]
|
111
|
-
actual_count = @
|
122
|
+
actual_count = @_partials[expected_partial]
|
112
123
|
msg = build_message(message,
|
113
124
|
"expecting ? to be rendered ? time(s) but rendered ? time(s)",
|
114
125
|
expected_partial, expected_count, actual_count)
|
@@ -116,11 +127,11 @@ module ActionController
|
|
116
127
|
else
|
117
128
|
msg = build_message(message,
|
118
129
|
"expecting partial <?> but action rendered <?>",
|
119
|
-
options[:partial], @
|
120
|
-
assert(@
|
130
|
+
options[:partial], @_partials.keys)
|
131
|
+
assert(@_partials.include?(expected_partial), msg)
|
121
132
|
end
|
122
133
|
else
|
123
|
-
assert @
|
134
|
+
assert @_partials.empty?,
|
124
135
|
"Expected no partials to be rendered"
|
125
136
|
end
|
126
137
|
end
|
@@ -422,7 +433,7 @@ module ActionController
|
|
422
433
|
Hash[hash_or_array_or_value.map{|key, value| [key, paramify_values(value)] }]
|
423
434
|
when Array
|
424
435
|
hash_or_array_or_value.map {|i| paramify_values(i)}
|
425
|
-
when Rack::Test::UploadedFile
|
436
|
+
when Rack::Test::UploadedFile, ActionDispatch::Http::UploadedFile
|
426
437
|
hash_or_array_or_value
|
427
438
|
else
|
428
439
|
hash_or_array_or_value.to_param
|
@@ -19,7 +19,7 @@ module ActionDispatch
|
|
19
19
|
[:open, :path, :rewind, :size].each do |method|
|
20
20
|
class_eval "def #{method}; @tempfile.#{method}; end"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
private
|
24
24
|
def encode_filename(filename)
|
25
25
|
# Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8
|
@@ -170,12 +170,14 @@ module ActionDispatch
|
|
170
170
|
options = { :value => value }
|
171
171
|
end
|
172
172
|
|
173
|
-
@cookies[key.to_s] = value
|
174
|
-
|
175
173
|
handle_options(options)
|
176
174
|
|
177
|
-
@
|
178
|
-
|
175
|
+
if @cookies[key.to_s] != value or options[:expires]
|
176
|
+
@cookies[key.to_s] = value
|
177
|
+
@set_cookies[key.to_s] = options
|
178
|
+
@delete_cookies.delete(key.to_s)
|
179
|
+
end
|
180
|
+
|
179
181
|
value
|
180
182
|
end
|
181
183
|
|
@@ -34,7 +34,7 @@ module ActionDispatch
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def status_code
|
37
|
-
|
37
|
+
self.class.status_code_for_exception(@exception.class.name)
|
38
38
|
end
|
39
39
|
|
40
40
|
def application_trace
|
@@ -49,6 +49,10 @@ module ActionDispatch
|
|
49
49
|
clean_backtrace(:all)
|
50
50
|
end
|
51
51
|
|
52
|
+
def self.status_code_for_exception(class_name)
|
53
|
+
Rack::Utils.status_code(@@rescue_responses[class_name])
|
54
|
+
end
|
55
|
+
|
52
56
|
private
|
53
57
|
|
54
58
|
def original_exception(exception)
|
@@ -75,4 +79,4 @@ module ActionDispatch
|
|
75
79
|
@backtrace_cleaner ||= @env['action_dispatch.backtrace_cleaner']
|
76
80
|
end
|
77
81
|
end
|
78
|
-
end
|
82
|
+
end
|
@@ -74,6 +74,13 @@ module ActionDispatch
|
|
74
74
|
class AbstractStore < Rack::Session::Abstract::ID
|
75
75
|
include Compatibility
|
76
76
|
include StaleSessionCheck
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def set_cookie(env, session_id, cookie)
|
81
|
+
request = ActionDispatch::Request.new(env)
|
82
|
+
request.cookie_jar[key] = cookie
|
83
|
+
end
|
77
84
|
end
|
78
85
|
end
|
79
86
|
end
|
@@ -166,7 +166,7 @@ module ActionDispatch
|
|
166
166
|
controller ||= default_controller
|
167
167
|
action ||= default_action
|
168
168
|
|
169
|
-
unless controller.is_a?(Regexp)
|
169
|
+
unless controller.is_a?(Regexp)
|
170
170
|
controller = [@scope[:module], controller].compact.join("/").presence
|
171
171
|
end
|
172
172
|
|
@@ -982,7 +982,7 @@ module ActionDispatch
|
|
982
982
|
# === Options
|
983
983
|
# Takes same options as +resources+.
|
984
984
|
def resource(*resources, &block)
|
985
|
-
options = resources.extract_options
|
985
|
+
options = resources.extract_options!.dup
|
986
986
|
|
987
987
|
if apply_common_behavior_for(:resource, resources, options, &block)
|
988
988
|
return self
|
@@ -1120,7 +1120,7 @@ module ActionDispatch
|
|
1120
1120
|
# # resource actions are at /admin/posts.
|
1121
1121
|
# resources :posts, :path => "admin/posts"
|
1122
1122
|
def resources(*resources, &block)
|
1123
|
-
options = resources.extract_options
|
1123
|
+
options = resources.extract_options!.dup
|
1124
1124
|
|
1125
1125
|
if apply_common_behavior_for(:resources, resources, options, &block)
|
1126
1126
|
return self
|
@@ -18,8 +18,8 @@ module ActionDispatch
|
|
18
18
|
# a Hash, or a String that is appropriately encoded
|
19
19
|
# (<tt>application/x-www-form-urlencoded</tt> or
|
20
20
|
# <tt>multipart/form-data</tt>).
|
21
|
-
# - +headers+: Additional
|
22
|
-
#
|
21
|
+
# - +headers+: Additional headers to pass, as a Hash. The headers will be
|
22
|
+
# merged into the Rack env hash.
|
23
23
|
#
|
24
24
|
# This method returns an Response object, which one can use to
|
25
25
|
# inspect the details of the response. Furthermore, if this method was
|
@@ -62,8 +62,7 @@ module ActionDispatch
|
|
62
62
|
#
|
63
63
|
# The request_method is +:get+, +:post+, +:put+, +:delete+ or +:head+; the
|
64
64
|
# parameters are +nil+, a hash, or a url-encoded or multipart string;
|
65
|
-
# the headers are a hash.
|
66
|
-
# with 'HTTP_' if not already.
|
65
|
+
# the headers are a hash.
|
67
66
|
def xml_http_request(request_method, path, parameters = nil, headers = nil)
|
68
67
|
headers ||= {}
|
69
68
|
headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
@@ -12,7 +12,7 @@ module ActionDispatch
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def initialize(env = {})
|
15
|
-
env = Rails.application.env_config.merge(env) if defined?(Rails.application)
|
15
|
+
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
|
16
16
|
super(DEFAULT_ENV.merge(env))
|
17
17
|
|
18
18
|
self.host = 'test.host'
|
data/lib/action_pack/version.rb
CHANGED
@@ -27,7 +27,8 @@ module ActionView
|
|
27
27
|
|
28
28
|
def expand_sources(sources, recursive = false)
|
29
29
|
if sources.include?(:all)
|
30
|
-
all_asset_files = (collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}") - ['application'])
|
30
|
+
all_asset_files = (collect_asset_files(custom_dir, ('**' if recursive), "*.#{extension}") - ['application'])
|
31
|
+
add_application_js(all_asset_files, sources)
|
31
32
|
((determine_source(:defaults, expansions).dup & all_asset_files) + all_asset_files).uniq
|
32
33
|
else
|
33
34
|
expanded_sources = sources.inject([]) do |list, source|
|
@@ -40,7 +41,7 @@ module ActionView
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def add_application_js(expanded_sources, sources)
|
43
|
-
if sources.include?(:defaults) && File.exist?(File.join(custom_dir, "application.#{extension}"))
|
44
|
+
if (sources.include?(:defaults) || sources.include?(:all)) && File.exist?(File.join(custom_dir, "application.#{extension}"))
|
44
45
|
expanded_sources.delete('application')
|
45
46
|
expanded_sources << "application"
|
46
47
|
end
|
@@ -101,8 +102,8 @@ module ActionView
|
|
101
102
|
#
|
102
103
|
# config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js)
|
103
104
|
#
|
104
|
-
# When using <tt>:defaults</tt>, if an <tt>application.js</tt> file exists
|
105
|
-
# <tt>public/javascripts</tt> it will be included as well at the end.
|
105
|
+
# When using <tt>:defaults</tt> or <tt>:all</tt>, if an <tt>application.js</tt> file exists
|
106
|
+
# in <tt>public/javascripts</tt> it will be included as well at the end.
|
106
107
|
#
|
107
108
|
# You can modify the HTML attributes of the script tag by passing a hash as the
|
108
109
|
# last argument.
|
@@ -129,16 +130,16 @@ module ActionView
|
|
129
130
|
# # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
|
130
131
|
# # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
|
131
132
|
#
|
132
|
-
#
|
133
|
+
# Note: The application.js file is only referenced if it exists
|
133
134
|
#
|
134
135
|
# You can also include all JavaScripts in the +javascripts+ directory using <tt>:all</tt> as the source:
|
135
136
|
#
|
136
137
|
# javascript_include_tag :all
|
137
138
|
# # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
|
138
139
|
# # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
|
139
|
-
# # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
|
140
140
|
# # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
|
141
141
|
# # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
|
142
|
+
# # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
|
142
143
|
#
|
143
144
|
# Note that your defaults of choice will be included first, so they will be available to all subsequently
|
144
145
|
# included files.
|
@@ -161,9 +162,9 @@ module ActionView
|
|
161
162
|
# javascript_include_tag :all, :cache => true
|
162
163
|
# # => <script type="text/javascript" src="/javascripts/jquery.js?1284139606"></script>
|
163
164
|
# # <script type="text/javascript" src="/javascripts/rails.js?1284139606"></script>
|
164
|
-
# # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
|
165
165
|
# # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
|
166
166
|
# # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
|
167
|
+
# # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
|
167
168
|
#
|
168
169
|
# # assuming config.perform_caching is true
|
169
170
|
# javascript_include_tag :all, :cache => true
|
@@ -915,12 +915,15 @@ module ActionView
|
|
915
915
|
# build_hidden(:year, 2008)
|
916
916
|
# => "<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="2008" />"
|
917
917
|
def build_hidden(type, value)
|
918
|
-
|
918
|
+
select_options = {
|
919
919
|
:type => "hidden",
|
920
920
|
:id => input_id_from_type(type),
|
921
921
|
:name => input_name_from_type(type),
|
922
922
|
:value => value
|
923
|
-
}.merge(@html_options.slice(:disabled))
|
923
|
+
}.merge(@html_options.slice(:disabled))
|
924
|
+
select_options.merge!(:disabled => 'disabled') if @options[:disabled]
|
925
|
+
|
926
|
+
tag(:input, select_options) + "\n".html_safe
|
924
927
|
end
|
925
928
|
|
926
929
|
# Returns the name attribute for the input tag.
|
@@ -119,6 +119,7 @@ module ActionView
|
|
119
119
|
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
|
120
120
|
# # <option>Paris</option><option>Rome</option></select>
|
121
121
|
def select_tag(name, option_tags = nil, options = {})
|
122
|
+
option_tags ||= ""
|
122
123
|
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
|
123
124
|
|
124
125
|
if options.delete(:include_blank)
|
@@ -633,7 +633,9 @@ module ActionView
|
|
633
633
|
end
|
634
634
|
|
635
635
|
def link_to_remote_options?(options)
|
636
|
-
options.is_a?(Hash)
|
636
|
+
if options.is_a?(Hash)
|
637
|
+
options.delete('remote') || options.delete(:remote)
|
638
|
+
end
|
637
639
|
end
|
638
640
|
|
639
641
|
def add_method_to_attributes!(html_options, method)
|
@@ -193,16 +193,16 @@ module ActionView
|
|
193
193
|
@_result
|
194
194
|
@_routes
|
195
195
|
@controller
|
196
|
-
@
|
196
|
+
@_layouts
|
197
197
|
@locals
|
198
198
|
@method_name
|
199
199
|
@output_buffer
|
200
|
-
@
|
200
|
+
@_partials
|
201
201
|
@passed
|
202
202
|
@rendered
|
203
203
|
@request
|
204
204
|
@routes
|
205
|
-
@
|
205
|
+
@_templates
|
206
206
|
@options
|
207
207
|
@test_passed
|
208
208
|
@view
|