actionpack 1.7.0 → 1.8.0
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 +109 -0
- data/README +2 -2
- data/RUNNING_UNIT_TESTS +1 -1
- data/install.rb +8 -77
- data/lib/action_controller/assertions.rb +203 -0
- data/lib/action_controller/base.rb +15 -7
- data/lib/action_controller/benchmarking.rb +10 -4
- data/lib/action_controller/caching.rb +28 -17
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +5 -9
- data/lib/action_controller/cgi_process.rb +5 -1
- data/lib/action_controller/cookies.rb +3 -2
- data/lib/action_controller/deprecated_assertions.rb +204 -0
- data/lib/action_controller/flash.rb +30 -36
- data/lib/action_controller/pagination.rb +4 -4
- data/lib/action_controller/request.rb +18 -2
- data/lib/action_controller/routing.rb +6 -2
- data/lib/action_controller/scaffolding.rb +1 -1
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +1 -1
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -2
- data/lib/action_controller/templates/rescues/template_error.rhtml +5 -4
- data/lib/action_controller/templates/scaffolds/list.rhtml +3 -0
- data/lib/action_controller/test_process.rb +60 -17
- data/lib/action_controller/url_rewriter.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/document.rb +63 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +431 -0
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +95 -0
- data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_controller/verification.rb +13 -4
- data/lib/action_view/base.rb +3 -2
- data/lib/action_view/helpers/active_record_helper.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +31 -9
- data/lib/action_view/helpers/date_helper.rb +25 -22
- data/lib/action_view/helpers/form_helper.rb +6 -5
- data/lib/action_view/helpers/form_options_helper.rb +4 -4
- data/lib/action_view/helpers/javascript_helper.rb +28 -6
- data/lib/action_view/helpers/javascripts/prototype.js +340 -30
- data/lib/action_view/helpers/number_helper.rb +110 -0
- data/lib/action_view/helpers/pagination_helper.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +8 -21
- data/lib/action_view/helpers/url_helper.rb +21 -4
- data/lib/action_view/partials.rb +39 -9
- data/rakefile +29 -5
- data/test/abstract_unit.rb +1 -0
- data/test/controller/action_pack_assertions_test.rb +1 -2
- data/test/controller/active_record_assertions_test.rb +1 -1
- data/test/controller/cgi_test.rb +0 -1
- data/test/controller/cookie_test.rb +11 -1
- data/test/controller/helper_test.rb +0 -12
- data/test/controller/render_test.rb +9 -0
- data/test/controller/request_test.rb +44 -1
- data/test/controller/routing_tests.rb +4 -1
- data/test/controller/test_test.rb +62 -0
- data/test/controller/verification_test.rb +21 -0
- data/test/fixtures/test/_partial_only.rhtml +1 -0
- data/test/template/active_record_helper_test.rb +2 -2
- data/test/template/asset_tag_helper_test.rb +52 -4
- data/test/template/date_helper_test.rb +163 -32
- data/test/template/form_helper_test.rb +9 -6
- data/test/template/form_options_helper_test.rb +18 -15
- data/test/template/number_helper_test.rb +51 -0
- data/test/template/text_helper_test.rb +17 -20
- data/test/template/url_helper_test.rb +7 -1
- metadata +15 -6
- data/lib/action_controller/assertions/action_pack_assertions.rb +0 -260
- data/lib/action_controller/assertions/active_record_assertions.rb +0 -65
@@ -19,7 +19,11 @@ module ActionController #:nodoc:
|
|
19
19
|
if logger.nil?
|
20
20
|
render_without_benchmark(template_name, status)
|
21
21
|
else
|
22
|
+
db_runtime = ActiveRecord::Base.connection.reset_runtime
|
22
23
|
@rendering_runtime = Benchmark::measure{ render_without_benchmark(template_name, status) }.real
|
24
|
+
@db_rt_before_render = db_runtime
|
25
|
+
@db_rt_after_render = ActiveRecord::Base.connection.reset_runtime
|
26
|
+
@rendering_runtime -= @db_rt_after_render
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
@@ -28,7 +32,7 @@ module ActionController #:nodoc:
|
|
28
32
|
perform_action_without_benchmark
|
29
33
|
else
|
30
34
|
runtime = [Benchmark::measure{ perform_action_without_benchmark }.real, 0.0001].max
|
31
|
-
log_message = "Completed in #{sprintf("
|
35
|
+
log_message = "Completed in #{sprintf("%.5f", runtime)} (#{(1 / runtime).floor} reqs/sec)"
|
32
36
|
log_message << rendering_runtime(runtime) if @rendering_runtime
|
33
37
|
log_message << active_record_runtime(runtime) if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
|
34
38
|
logger.info(log_message)
|
@@ -37,13 +41,15 @@ module ActionController #:nodoc:
|
|
37
41
|
|
38
42
|
private
|
39
43
|
def rendering_runtime(runtime)
|
40
|
-
" | Rendering: #{sprintf("
|
44
|
+
" | Rendering: #{sprintf("%.5f", @rendering_runtime)} (#{sprintf("%d", (@rendering_runtime * 100) / runtime)}%)"
|
41
45
|
end
|
42
46
|
|
43
47
|
def active_record_runtime(runtime)
|
44
48
|
db_runtime = ActiveRecord::Base.connection.reset_runtime
|
45
|
-
|
46
|
-
|
49
|
+
db_runtime += @db_rt_before_render if @db_rt_before_render
|
50
|
+
db_runtime += @db_rt_after_render if @db_rt_after_render
|
51
|
+
db_percentage = (db_runtime * 100) / runtime
|
52
|
+
" | DB: #{sprintf("%.5f", db_runtime)} (#{sprintf("%d", db_percentage)}%)"
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
@@ -99,7 +99,7 @@ module ActionController #:nodoc:
|
|
99
99
|
private
|
100
100
|
def page_cache_file(path)
|
101
101
|
name = ((path.empty? || path == "/") ? "/index" : path)
|
102
|
-
name <<
|
102
|
+
name << page_cache_extension unless (name.split('/').last || name).include? '.'
|
103
103
|
return name
|
104
104
|
end
|
105
105
|
|
@@ -114,10 +114,10 @@ module ActionController #:nodoc:
|
|
114
114
|
return unless perform_caching
|
115
115
|
if options[:action].is_a?(Array)
|
116
116
|
options[:action].dup.each do |action|
|
117
|
-
self.class.expire_page(url_for(options.merge({ :only_path => true, :action => action })))
|
117
|
+
self.class.expire_page(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true, :action => action })))
|
118
118
|
end
|
119
119
|
else
|
120
|
-
self.class.expire_page(url_for(options.merge({ :only_path => true })))
|
120
|
+
self.class.expire_page(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true })))
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -126,7 +126,7 @@ module ActionController #:nodoc:
|
|
126
126
|
# cache_page "I'm the cached content", :controller => "lists", :action => "show"
|
127
127
|
def cache_page(content = nil, options = {})
|
128
128
|
return unless perform_caching && caching_allowed
|
129
|
-
self.class.cache_page(content || @response.body, url_for(options.merge({ :only_path => true })))
|
129
|
+
self.class.cache_page(content || @response.body, url_for(options.merge({ :only_path => true, :skip_relative_url_root => true })))
|
130
130
|
end
|
131
131
|
|
132
132
|
private
|
@@ -256,6 +256,15 @@ module ActionController #:nodoc:
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
|
+
def cache_base_url
|
260
|
+
@@cache_base_url ||= url_for(:controller => '')
|
261
|
+
end
|
262
|
+
|
263
|
+
def fragment_cache_key(name)
|
264
|
+
key = name.is_a?(Hash) ? url_for(name) : cache_base_url + name
|
265
|
+
key.split("://").last
|
266
|
+
end
|
267
|
+
|
259
268
|
# Called by CacheHelper#cache
|
260
269
|
def cache_erb_fragment(block, name = {}, options = {})
|
261
270
|
unless perform_caching then block.call; return end
|
@@ -272,16 +281,16 @@ module ActionController #:nodoc:
|
|
272
281
|
end
|
273
282
|
|
274
283
|
def write_fragment(name, content, options = {})
|
275
|
-
|
276
|
-
fragment_cache_store.write(
|
277
|
-
logger.info "Cached fragment: #{
|
284
|
+
key = fragment_cache_key(name)
|
285
|
+
fragment_cache_store.write(key, content, options)
|
286
|
+
logger.info "Cached fragment: #{key}" unless logger.nil?
|
278
287
|
content
|
279
288
|
end
|
280
289
|
|
281
290
|
def read_fragment(name, options = {})
|
282
|
-
|
283
|
-
if cache = fragment_cache_store.read(
|
284
|
-
logger.info "Fragment hit: #{
|
291
|
+
key = fragment_cache_key(name)
|
292
|
+
if cache = fragment_cache_store.read(key, options)
|
293
|
+
logger.info "Fragment hit: #{key}" unless logger.nil?
|
285
294
|
cache
|
286
295
|
else
|
287
296
|
false
|
@@ -289,14 +298,15 @@ module ActionController #:nodoc:
|
|
289
298
|
end
|
290
299
|
|
291
300
|
def expire_fragment(name, options = {})
|
292
|
-
|
293
|
-
fragment_cache_store.delete(
|
294
|
-
logger.info "Expired fragment: #{
|
301
|
+
key = fragment_cache_key(name)
|
302
|
+
fragment_cache_store.delete(key, options)
|
303
|
+
logger.info "Expired fragment: #{key}" unless logger.nil?
|
295
304
|
end
|
296
305
|
|
297
|
-
def expire_matched_fragments(re=Regexp.new('
|
298
|
-
|
299
|
-
|
306
|
+
def expire_matched_fragments(re=Regexp.new('/.*/'), options = {})
|
307
|
+
rp = cache_base_url.split("://").last
|
308
|
+
fragment_cache_store.delete_matched(re, { :root_path => rp })
|
309
|
+
logger.info "Expired all fragments matching: #{rp}#{re.source}" unless logger.nil?
|
300
310
|
end
|
301
311
|
|
302
312
|
class MemoryStore #:nodoc:
|
@@ -317,7 +327,8 @@ module ActionController #:nodoc:
|
|
317
327
|
end
|
318
328
|
|
319
329
|
def delete_matched(re, options) #:nodoc:
|
320
|
-
|
330
|
+
re = Regexp.new("#{Regexp.escape(options[:root_path])}#{re.source}")
|
331
|
+
@mutex.synchronize { @data.delete_if { |k,v| k =~ re } }
|
321
332
|
end
|
322
333
|
end
|
323
334
|
|
@@ -11,7 +11,7 @@ class CGI #:nodoc:
|
|
11
11
|
@params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
|
12
12
|
else
|
13
13
|
@multipart = false
|
14
|
-
@params = CGI::parse(read_query_params)
|
14
|
+
@params = CGI::parse(read_query_params || "")
|
15
15
|
end
|
16
16
|
|
17
17
|
@cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] || env_table['COOKIE']))
|
@@ -28,16 +28,12 @@ class CGI #:nodoc:
|
|
28
28
|
|
29
29
|
def read_query_params
|
30
30
|
case env_table['REQUEST_METHOD']
|
31
|
-
when 'GET', 'HEAD'
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
env_table['QUERY_STRING'] || ''
|
36
|
-
end
|
37
|
-
when 'POST'
|
31
|
+
when 'GET', 'HEAD', 'DELETE', 'OPTIONS'
|
32
|
+
(defined?(MOD_RUBY) ? Apache::request.args : env_table['QUERY_STRING']) || ''
|
33
|
+
when 'POST', 'PUT'
|
38
34
|
stdinput.binmode if stdinput.respond_to?(:binmode)
|
39
35
|
content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || ''
|
40
|
-
env_table['RAW_POST_DATA'] = content.split("&_").first.freeze # &_ is a fix for Safari Ajax postings that always append \000
|
36
|
+
env_table['RAW_POST_DATA'] = content.split("&_").first.to_s.freeze # &_ is a fix for Safari Ajax postings that always append \000
|
41
37
|
else
|
42
38
|
read_from_cmdline
|
43
39
|
end
|
@@ -48,7 +48,11 @@ module ActionController #:nodoc:
|
|
48
48
|
|
49
49
|
def query_string
|
50
50
|
return @cgi.query_string unless @cgi.query_string.nil? || @cgi.query_string.empty?
|
51
|
-
|
51
|
+
unless env['REQUEST_URI'].nil?
|
52
|
+
parts = env['REQUEST_URI'].split('?')
|
53
|
+
else
|
54
|
+
return env['QUERY_STRING'] || ''
|
55
|
+
end
|
52
56
|
parts.shift
|
53
57
|
return parts.join('?')
|
54
58
|
end
|
@@ -54,9 +54,10 @@ module ActionController #:nodoc:
|
|
54
54
|
set_cookie(options)
|
55
55
|
end
|
56
56
|
|
57
|
-
# Removes the cookie on the client machine by setting the value to an empty string
|
57
|
+
# Removes the cookie on the client machine by setting the value to an empty string
|
58
|
+
# and setting its expiration date into the past
|
58
59
|
def delete(name)
|
59
|
-
set_cookie("name" => name.to_s, "value" => "")
|
60
|
+
set_cookie("name" => name.to_s, "value" => "", "expires" => Time.at(0))
|
60
61
|
end
|
61
62
|
|
62
63
|
private
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/assertions'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module Test #:nodoc:
|
6
|
+
module Unit #:nodoc:
|
7
|
+
module Assertions
|
8
|
+
def assert_success(message=nil) #:nodoc:
|
9
|
+
assert_response(:success, message)
|
10
|
+
end
|
11
|
+
|
12
|
+
def assert_redirect(message=nil) #:nodoc:
|
13
|
+
assert_response(:redirect, message)
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_rendered_file(expected=nil, message=nil) #:nodoc:
|
17
|
+
assert_template(expected, message)
|
18
|
+
end
|
19
|
+
|
20
|
+
# ensure that the session has an object with the specified name
|
21
|
+
def assert_session_has(key=nil, message=nil) #:nodoc:
|
22
|
+
msg = build_message(message, "<?> is not in the session <?>", key, @response.session)
|
23
|
+
assert_block(msg) { @response.has_session_object?(key) }
|
24
|
+
end
|
25
|
+
|
26
|
+
# ensure that the session has no object with the specified name
|
27
|
+
def assert_session_has_no(key=nil, message=nil) #:nodoc:
|
28
|
+
msg = build_message(message, "<?> is in the session <?>", key, @response.session)
|
29
|
+
assert_block(msg) { !@response.has_session_object?(key) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_session_equal(expected = nil, key = nil, message = nil) #:nodoc:
|
33
|
+
msg = build_message(message, "<?> expected in session['?'] but was <?>", expected, key, @response.session[key])
|
34
|
+
assert_block(msg) { expected == @response.session[key] }
|
35
|
+
end
|
36
|
+
|
37
|
+
# -- cookie assertions ---------------------------------------------------
|
38
|
+
|
39
|
+
def assert_no_cookie(key = nil, message = nil) #:nodoc:
|
40
|
+
actual = @response.cookies[key]
|
41
|
+
msg = build_message(message, "<?> not expected in cookies['?']", actual, key)
|
42
|
+
assert_block(msg) { actual.nil? or actual.empty? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_cookie_equal(expected = nil, key = nil, message = nil) #:nodoc:
|
46
|
+
actual = @response.cookies[key]
|
47
|
+
actual = actual.first if actual
|
48
|
+
msg = build_message(message, "<?> expected in cookies['?'] but was <?>", expected, key, actual)
|
49
|
+
assert_block(msg) { expected == actual }
|
50
|
+
end
|
51
|
+
|
52
|
+
# -- flash assertions ---------------------------------------------------
|
53
|
+
|
54
|
+
# ensure that the flash has an object with the specified name
|
55
|
+
def assert_flash_has(key=nil, message=nil) #:nodoc:
|
56
|
+
msg = build_message(message, "<?> is not in the flash <?>", key, @response.flash)
|
57
|
+
assert_block(msg) { @response.has_flash_object?(key) }
|
58
|
+
end
|
59
|
+
|
60
|
+
# ensure that the flash has no object with the specified name
|
61
|
+
def assert_flash_has_no(key=nil, message=nil) #:nodoc:
|
62
|
+
msg = build_message(message, "<?> is in the flash <?>", key, @response.flash)
|
63
|
+
assert_block(msg) { !@response.has_flash_object?(key) }
|
64
|
+
end
|
65
|
+
|
66
|
+
# ensure the flash exists
|
67
|
+
def assert_flash_exists(message=nil) #:nodoc:
|
68
|
+
msg = build_message(message, "the flash does not exist <?>", @response.session['flash'] )
|
69
|
+
assert_block(msg) { @response.has_flash? }
|
70
|
+
end
|
71
|
+
|
72
|
+
# ensure the flash does not exist
|
73
|
+
def assert_flash_not_exists(message=nil) #:nodoc:
|
74
|
+
msg = build_message(message, "the flash exists <?>", @response.flash)
|
75
|
+
assert_block(msg) { !@response.has_flash? }
|
76
|
+
end
|
77
|
+
|
78
|
+
# ensure the flash is empty but existent
|
79
|
+
def assert_flash_empty(message=nil) #:nodoc:
|
80
|
+
msg = build_message(message, "the flash is not empty <?>", @response.flash)
|
81
|
+
assert_block(msg) { !@response.has_flash_with_contents? }
|
82
|
+
end
|
83
|
+
|
84
|
+
# ensure the flash is not empty
|
85
|
+
def assert_flash_not_empty(message=nil) #:nodoc:
|
86
|
+
msg = build_message(message, "the flash is empty")
|
87
|
+
assert_block(msg) { @response.has_flash_with_contents? }
|
88
|
+
end
|
89
|
+
|
90
|
+
def assert_flash_equal(expected = nil, key = nil, message = nil) #:nodoc:
|
91
|
+
msg = build_message(message, "<?> expected in flash['?'] but was <?>", expected, key, @response.flash[key])
|
92
|
+
assert_block(msg) { expected == @response.flash[key] }
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# ensure our redirection url is an exact match
|
97
|
+
def assert_redirect_url(url=nil, message=nil) #:nodoc:
|
98
|
+
assert_redirect(message)
|
99
|
+
msg = build_message(message, "<?> is not the redirected location <?>", url, @response.redirect_url)
|
100
|
+
assert_block(msg) { @response.redirect_url == url }
|
101
|
+
end
|
102
|
+
|
103
|
+
# ensure our redirection url matches a pattern
|
104
|
+
def assert_redirect_url_match(pattern=nil, message=nil) #:nodoc:
|
105
|
+
assert_redirect(message)
|
106
|
+
msg = build_message(message, "<?> was not found in the location: <?>", pattern, @response.redirect_url)
|
107
|
+
assert_block(msg) { @response.redirect_url_match?(pattern) }
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# -- template assertions ------------------------------------------------
|
112
|
+
|
113
|
+
# ensure that a template object with the given name exists
|
114
|
+
def assert_template_has(key=nil, message=nil) #:nodoc:
|
115
|
+
msg = build_message(message, "<?> is not a template object", key )
|
116
|
+
assert_block(msg) { @response.has_template_object?(key) }
|
117
|
+
end
|
118
|
+
|
119
|
+
# ensure that a template object with the given name does not exist
|
120
|
+
def assert_template_has_no(key=nil,message=nil) #:nodoc:
|
121
|
+
msg = build_message(message, "<?> is a template object <?>", key, @response.template_objects[key])
|
122
|
+
assert_block(msg) { !@response.has_template_object?(key) }
|
123
|
+
end
|
124
|
+
|
125
|
+
# ensures that the object assigned to the template on +key+ is equal to +expected+ object.
|
126
|
+
def assert_template_equal(expected = nil, key = nil, message = nil) #:nodoc:
|
127
|
+
msg = build_message(message, "<?> expected in assigns['?'] but was <?>", expected, key, @response.template.assigns[key.to_s])
|
128
|
+
assert_block(msg) { expected == @response.template.assigns[key.to_s] }
|
129
|
+
end
|
130
|
+
alias_method :assert_assigned_equal, :assert_template_equal
|
131
|
+
|
132
|
+
# Asserts that the template returns the +expected+ string or array based on the XPath +expression+.
|
133
|
+
# This will only work if the template rendered a valid XML document.
|
134
|
+
def assert_template_xpath_match(expression=nil, expected=nil, message=nil) #:nodoc:
|
135
|
+
xml, matches = REXML::Document.new(@response.body), []
|
136
|
+
xml.elements.each(expression) { |e| matches << e.text }
|
137
|
+
if matches.empty? then
|
138
|
+
msg = build_message(message, "<?> not found in document", expression)
|
139
|
+
flunk(msg)
|
140
|
+
return
|
141
|
+
elsif matches.length < 2 then
|
142
|
+
matches = matches.first
|
143
|
+
end
|
144
|
+
|
145
|
+
msg = build_message(message, "<?> found <?>, not <?>", expression, matches, expected)
|
146
|
+
assert_block(msg) { matches == expected }
|
147
|
+
end
|
148
|
+
|
149
|
+
# Assert the template object with the given name is an Active Record descendant and is valid.
|
150
|
+
def assert_valid_record(key = nil, message = nil) #:nodoc:
|
151
|
+
record = find_record_in_template(key)
|
152
|
+
msg = build_message(message, "Active Record is invalid <?>)", record.errors.full_messages)
|
153
|
+
assert_block(msg) { record.valid? }
|
154
|
+
end
|
155
|
+
|
156
|
+
# Assert the template object with the given name is an Active Record descendant and is invalid.
|
157
|
+
def assert_invalid_record(key = nil, message = nil) #:nodoc:
|
158
|
+
record = find_record_in_template(key)
|
159
|
+
msg = build_message(message, "Active Record is valid)")
|
160
|
+
assert_block(msg) { !record.valid? }
|
161
|
+
end
|
162
|
+
|
163
|
+
# Assert the template object with the given name is an Active Record descendant and the specified column(s) are valid.
|
164
|
+
def assert_valid_column_on_record(key = nil, columns = "", message = nil) #:nodoc:
|
165
|
+
record = find_record_in_template(key)
|
166
|
+
record.send(:validate)
|
167
|
+
|
168
|
+
cols = glue_columns(columns)
|
169
|
+
cols.delete_if { |col| !record.errors.invalid?(col) }
|
170
|
+
msg = build_message(message, "Active Record has invalid columns <?>)", cols.join(",") )
|
171
|
+
assert_block(msg) { cols.empty? }
|
172
|
+
end
|
173
|
+
|
174
|
+
# Assert the template object with the given name is an Active Record descendant and the specified column(s) are invalid.
|
175
|
+
def assert_invalid_column_on_record(key = nil, columns = "", message = nil) #:nodoc:
|
176
|
+
record = find_record_in_template(key)
|
177
|
+
record.send(:validate)
|
178
|
+
|
179
|
+
cols = glue_columns(columns)
|
180
|
+
cols.delete_if { |col| record.errors.invalid?(col) }
|
181
|
+
msg = build_message(message, "Active Record has valid columns <?>)", cols.join(",") )
|
182
|
+
assert_block(msg) { cols.empty? }
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
def glue_columns(columns)
|
187
|
+
cols = []
|
188
|
+
cols << columns if columns.class == String
|
189
|
+
cols += columns if columns.class == Array
|
190
|
+
cols
|
191
|
+
end
|
192
|
+
|
193
|
+
def find_record_in_template(key = nil)
|
194
|
+
assert_template_has(key)
|
195
|
+
record = @response.template_objects[key]
|
196
|
+
|
197
|
+
assert_not_nil(record)
|
198
|
+
assert_kind_of ActiveRecord::Base, record
|
199
|
+
|
200
|
+
return record
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -24,7 +24,6 @@ module ActionController #:nodoc:
|
|
24
24
|
#
|
25
25
|
# See docs on the FlashHash class for more details about the flash.
|
26
26
|
module Flash
|
27
|
-
|
28
27
|
def self.append_features(base) #:nodoc:
|
29
28
|
super
|
30
29
|
base.before_filter(:fire_flash)
|
@@ -44,7 +43,6 @@ module ActionController #:nodoc:
|
|
44
43
|
end
|
45
44
|
|
46
45
|
class FlashHash < Hash
|
47
|
-
|
48
46
|
def initialize #:nodoc:
|
49
47
|
super
|
50
48
|
@used = {}
|
@@ -113,49 +111,45 @@ module ActionController #:nodoc:
|
|
113
111
|
end
|
114
112
|
|
115
113
|
private
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
114
|
+
# Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
|
115
|
+
# use() # marks the entire flash as used
|
116
|
+
# use('msg') # marks the "msg" entry as used
|
117
|
+
# use(nil, false) # marks the entire flash as unused (keeps it around for one more action)
|
118
|
+
# use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
|
119
|
+
def use(k=nil, v=true)
|
120
|
+
unless k.nil?
|
121
|
+
@used[k] = v
|
122
|
+
else
|
123
|
+
keys.each{|key| use key, v }
|
124
|
+
end
|
127
125
|
end
|
128
|
-
end
|
129
|
-
|
130
126
|
end
|
131
127
|
|
132
128
|
|
133
129
|
protected
|
130
|
+
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or
|
131
|
+
# <tt>flash["notice"] = "hello"</tt> to put a new one.
|
132
|
+
def flash #:doc:
|
133
|
+
@session['flash'] ||= FlashHash.new
|
134
|
+
end
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
# deprecated. use <tt>flash.keep</tt> instead
|
142
|
-
def keep_flash #:doc:
|
143
|
-
flash.keep
|
144
|
-
end
|
145
|
-
|
136
|
+
# deprecated. use <tt>flash.keep</tt> instead
|
137
|
+
def keep_flash #:doc:
|
138
|
+
flash.keep
|
139
|
+
end
|
146
140
|
|
147
|
-
private
|
148
141
|
|
149
|
-
|
150
|
-
def fire_flash
|
151
|
-
flash.discard
|
152
|
-
@assigns["flash"] = flash
|
153
|
-
end
|
142
|
+
private
|
154
143
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
144
|
+
# marks flash entries as used and expose the flash to the view
|
145
|
+
def fire_flash
|
146
|
+
flash.discard
|
147
|
+
@assigns["flash"] = flash
|
148
|
+
end
|
159
149
|
|
150
|
+
# deletes the flash entries that were not marked for keeping
|
151
|
+
def sweep_flash
|
152
|
+
flash.sweep
|
153
|
+
end
|
160
154
|
end
|
161
155
|
end
|