actionpack 1.8.1 → 1.9.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.

Files changed (101) hide show
  1. data/CHANGELOG +309 -16
  2. data/README +1 -1
  3. data/lib/action_controller.rb +5 -0
  4. data/lib/action_controller/assertions.rb +57 -12
  5. data/lib/action_controller/auto_complete.rb +47 -0
  6. data/lib/action_controller/base.rb +288 -258
  7. data/lib/action_controller/benchmarking.rb +8 -3
  8. data/lib/action_controller/caching.rb +88 -42
  9. data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
  10. data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
  11. data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
  12. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
  13. data/lib/action_controller/cgi_process.rb +39 -11
  14. data/lib/action_controller/code_generation.rb +235 -0
  15. data/lib/action_controller/cookies.rb +14 -8
  16. data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
  17. data/lib/action_controller/filters.rb +8 -7
  18. data/lib/action_controller/helpers.rb +41 -6
  19. data/lib/action_controller/layout.rb +45 -16
  20. data/lib/action_controller/request.rb +86 -23
  21. data/lib/action_controller/rescue.rb +1 -0
  22. data/lib/action_controller/response.rb +1 -1
  23. data/lib/action_controller/routing.rb +536 -272
  24. data/lib/action_controller/scaffolding.rb +30 -25
  25. data/lib/action_controller/session/active_record_store.rb +251 -50
  26. data/lib/action_controller/streaming.rb +133 -0
  27. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
  28. data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
  29. data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
  30. data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
  31. data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
  32. data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
  33. data/lib/action_controller/test_process.rb +68 -47
  34. data/lib/action_controller/upload_progress.rb +421 -0
  35. data/lib/action_controller/url_rewriter.rb +8 -11
  36. data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
  37. data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
  38. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
  39. data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
  40. data/lib/action_controller/vendor/xml_simple.rb +1019 -0
  41. data/lib/action_controller/verification.rb +36 -30
  42. data/lib/action_view/base.rb +21 -14
  43. data/lib/action_view/helpers/active_record_helper.rb +15 -13
  44. data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
  45. data/lib/action_view/helpers/benchmark_helper.rb +24 -0
  46. data/lib/action_view/helpers/capture_helper.rb +7 -5
  47. data/lib/action_view/helpers/date_helper.rb +63 -46
  48. data/lib/action_view/helpers/form_helper.rb +7 -1
  49. data/lib/action_view/helpers/form_options_helper.rb +19 -11
  50. data/lib/action_view/helpers/form_tag_helper.rb +5 -1
  51. data/lib/action_view/helpers/javascript_helper.rb +403 -35
  52. data/lib/action_view/helpers/javascripts/controls.js +261 -0
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
  54. data/lib/action_view/helpers/javascripts/effects.js +570 -0
  55. data/lib/action_view/helpers/javascripts/prototype.js +633 -371
  56. data/lib/action_view/helpers/number_helper.rb +11 -13
  57. data/lib/action_view/helpers/tag_helper.rb +1 -2
  58. data/lib/action_view/helpers/text_helper.rb +69 -6
  59. data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
  60. data/lib/action_view/helpers/url_helper.rb +98 -3
  61. data/lib/action_view/partials.rb +14 -8
  62. data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
  63. data/rakefile +13 -5
  64. data/test/abstract_unit.rb +1 -1
  65. data/test/controller/action_pack_assertions_test.rb +52 -9
  66. data/test/controller/active_record_assertions_test.rb +119 -120
  67. data/test/controller/active_record_store_test.rb +111 -0
  68. data/test/controller/addresses_render_test.rb +45 -0
  69. data/test/controller/caching_filestore.rb +92 -0
  70. data/test/controller/capture_test.rb +39 -0
  71. data/test/controller/cgi_test.rb +40 -3
  72. data/test/controller/helper_test.rb +65 -13
  73. data/test/controller/multipart_progress_testx.rb +365 -0
  74. data/test/controller/new_render_test.rb +263 -0
  75. data/test/controller/redirect_test.rb +64 -0
  76. data/test/controller/render_test.rb +20 -21
  77. data/test/controller/request_test.rb +83 -3
  78. data/test/controller/routing_test.rb +702 -0
  79. data/test/controller/send_file_test.rb +2 -0
  80. data/test/controller/test_test.rb +44 -8
  81. data/test/controller/upload_progress_testx.rb +89 -0
  82. data/test/controller/verification_test.rb +94 -29
  83. data/test/fixtures/addresses/list.rhtml +1 -0
  84. data/test/fixtures/test/capturing.rhtml +4 -0
  85. data/test/fixtures/test/list.rhtml +1 -1
  86. data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
  87. data/test/template/active_record_helper_test.rb +30 -15
  88. data/test/template/asset_tag_helper_test.rb +12 -5
  89. data/test/template/benchmark_helper_test.rb +72 -0
  90. data/test/template/date_helper_test.rb +69 -0
  91. data/test/template/form_helper_test.rb +18 -10
  92. data/test/template/form_options_helper_test.rb +40 -5
  93. data/test/template/javascript_helper.rb +149 -2
  94. data/test/template/number_helper_test.rb +2 -0
  95. data/test/template/tag_helper_test.rb +4 -0
  96. data/test/template/text_helper_test.rb +36 -0
  97. data/test/template/upload_progress_helper_testx.rb +272 -0
  98. data/test/template/url_helper_test.rb +30 -0
  99. metadata +30 -6
  100. data/test/controller/layout_test.rb +0 -49
  101. data/test/controller/routing_tests.rb +0 -543
@@ -0,0 +1,133 @@
1
+ module ActionController #:nodoc:
2
+ # Methods for sending files and streams to the browser instead of rendering.
3
+ module Streaming
4
+ DEFAULT_SEND_FILE_OPTIONS = {
5
+ :type => 'application/octet-stream'.freeze,
6
+ :disposition => 'attachment'.freeze,
7
+ :stream => true,
8
+ :buffer_size => 4096
9
+ }.freeze
10
+
11
+ protected
12
+ # Sends the file by streaming it 4096 bytes at a time. This way the
13
+ # whole file doesn't need to be read into memory at once. This makes
14
+ # it feasible to send even large files.
15
+ #
16
+ # Be careful to sanitize the path parameter if it coming from a web
17
+ # page. send_file(@params['path']) allows a malicious user to
18
+ # download any file on your server.
19
+ #
20
+ # Options:
21
+ # * <tt>:filename</tt> - suggests a filename for the browser to use.
22
+ # Defaults to File.basename(path).
23
+ # * <tt>:type</tt> - specifies an HTTP content type.
24
+ # Defaults to 'application/octet-stream'.
25
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
26
+ # Valid values are 'inline' and 'attachment' (default).
27
+ # * <tt>:stream</tt> - whether to send the file to the user agent as it is read (true)
28
+ # or to read the entire file before sending (false). Defaults to true.
29
+ # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
30
+ # Defaults to 4096.
31
+ #
32
+ # The default Content-Type and Content-Disposition headers are
33
+ # set to download arbitrary binary files in as many browsers as
34
+ # possible. IE versions 4, 5, 5.5, and 6 are all known to have
35
+ # a variety of quirks (especially when downloading over SSL).
36
+ #
37
+ # Simple download:
38
+ # send_file '/path/to.zip'
39
+ #
40
+ # Show a JPEG in browser:
41
+ # send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
42
+ #
43
+ # Read about the other Content-* HTTP headers if you'd like to
44
+ # provide the user with more information (such as Content-Description).
45
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
46
+ #
47
+ # Also be aware that the document may be cached by proxies and browsers.
48
+ # The Pragma and Cache-Control headers declare how the file may be cached
49
+ # by intermediaries. They default to require clients to validate with
50
+ # the server before releasing cached responses. See
51
+ # http://www.mnot.net/cache_docs/ for an overview of web caching and
52
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
53
+ # for the Cache-Control header spec.
54
+ def send_file(path, options = {}) #:doc:
55
+ raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
56
+
57
+ options[:length] ||= File.size(path)
58
+ options[:filename] ||= File.basename(path)
59
+ send_file_headers! options
60
+
61
+ @performed_render = false
62
+
63
+ if options[:stream]
64
+ render :text => Proc.new {
65
+ logger.info "Streaming file #{path}" unless logger.nil?
66
+ len = options[:buffer_size] || 4096
67
+ File.open(path, 'rb') do |file|
68
+ if $stdout.respond_to?(:syswrite)
69
+ begin
70
+ while true
71
+ $stdout.syswrite file.sysread(len)
72
+ end
73
+ rescue EOFError
74
+ end
75
+ else
76
+ while buf = file.read(len)
77
+ $stdout.write buf
78
+ end
79
+ end
80
+ end
81
+ }
82
+ else
83
+ logger.info "Sending file #{path}" unless logger.nil?
84
+ File.open(path, 'rb') { |file| render :text => file.read }
85
+ end
86
+ end
87
+
88
+ # Send binary data to the user as a file download. May set content type, apparent file name,
89
+ # and specify whether to show data inline or download as an attachment.
90
+ #
91
+ # Options:
92
+ # * <tt>:filename</tt> - Suggests a filename for the browser to use.
93
+ # * <tt>:type</tt> - specifies an HTTP content type.
94
+ # Defaults to 'application/octet-stream'.
95
+ # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
96
+ # Valid values are 'inline' and 'attachment' (default).
97
+ #
98
+ # Generic data download:
99
+ # send_data buffer
100
+ #
101
+ # Download a dynamically-generated tarball:
102
+ # send_data generate_tgz('dir'), :filename => 'dir.tgz'
103
+ #
104
+ # Display an image Active Record in the browser:
105
+ # send_data image.data, :type => image.content_type, :disposition => 'inline'
106
+ #
107
+ # See +send_file+ for more information on HTTP Content-* headers and caching.
108
+ def send_data(data, options = {}) #:doc:
109
+ logger.info "Sending data #{options[:filename]}" unless logger.nil?
110
+ send_file_headers! options.merge(:length => data.size)
111
+ @performed_render = false
112
+ render :text => data
113
+ end
114
+
115
+ private
116
+ def send_file_headers!(options)
117
+ options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
118
+ [:length, :type, :disposition].each do |arg|
119
+ raise ArgumentError, ":#{arg} option required" if options[arg].nil?
120
+ end
121
+
122
+ disposition = options[:disposition].dup || 'attachment'
123
+ disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
124
+
125
+ @headers.update(
126
+ 'Content-Length' => options[:length],
127
+ 'Content-Type' => options[:type].strip, # fixes a problem with extra '\r' with some browsers
128
+ 'Content-Disposition' => disposition,
129
+ 'Content-Transfer-Encoding' => 'binary'
130
+ );
131
+ end
132
+ end
133
+ end
@@ -33,10 +33,6 @@
33
33
  request_dump = request_parameters_without_action.inspect.gsub(/,/, ",\n")
34
34
  session_dump = @request.session.instance_variable_get("@data").inspect.gsub(/,/, ",\n")
35
35
  response_dump = @response.inspect.gsub(/,/, ",\n")
36
-
37
- template_assigns = @response.template.instance_variable_get("@assigns")
38
- %w( response exception template session request template_root template_class url ignore_missing_templates logger cookies headers params ).each { |t| template_assigns.delete(t) }
39
- template_dump = template_assigns.inspect.gsub(/,/, ",\n")
40
36
  %>
41
37
 
42
38
  <h2 style="margin-top: 30px">Request</h2>
@@ -48,6 +44,3 @@
48
44
 
49
45
  <h2 style="margin-top: 30px">Response</h2>
50
46
  <b>Headers</b>: <%=h @response.headers.inspect.gsub(/,/, ",\n") %><br/>
51
-
52
- <p><a href="#" onclick="document.getElementById('template_dump').style.display='block'; return false;">Show template parameters</a></p>
53
- <div id="template_dump" style="display:none"><%= debug(template_assigns) %></div>
@@ -1,7 +1,7 @@
1
1
  <h1>Editing <%= @scaffold_singular_name %></h1>
2
2
 
3
3
  <%= error_messages_for(@scaffold_singular_name) %>
4
- <%= form(@scaffold_singular_name, :action => "update" + @scaffold_suffix) %>
4
+ <%= form(@scaffold_singular_name, :action => "update#{@scaffold_suffix}") %>
5
5
 
6
- <%= link_to "Show", :action => "show#{@scaffold_suffix}", :id => instance_variable_get("@#{@scaffold_singular_name}").id %> |
6
+ <%= link_to "Show", :action => "show#{@scaffold_suffix}", :id => instance_variable_get("@#{@scaffold_singular_name}") %> |
7
7
  <%= link_to "Back", :action => "list#{@scaffold_suffix}" %>
@@ -1,3 +1,5 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
1
3
  <html>
2
4
  <head>
3
5
  <title>Scaffolding</title>
@@ -28,38 +30,40 @@
28
30
 
29
31
  #ErrorExplanation {
30
32
  width: 400px;
31
- border: 2px solid #red;
32
- padding: 7px;
33
- padding-bottom: 12px;
34
- margin-bottom: 20px;
35
- background-color: #f0f0f0;
33
+ border: 2px solid 'red';
34
+ padding: 7px;
35
+ padding-bottom: 12px;
36
+ margin-bottom: 20px;
37
+ background-color: #f0f0f0;
36
38
  }
37
39
 
38
40
  #ErrorExplanation h2 {
39
- text-align: left;
40
- font-weight: bold;
41
- padding: 5px 5px 5px 15px;
42
- font-size: 12px;
43
- margin: -7px;
44
- background-color: #c00;
45
- color: #fff;
41
+ text-align: left;
42
+ font-weight: bold;
43
+ padding: 5px 5px 5px 15px;
44
+ font-size: 12px;
45
+ margin: -7px;
46
+ background-color: #c00;
47
+ color: #fff;
46
48
  }
47
49
 
48
50
  #ErrorExplanation p {
49
- color: #333;
50
- margin-bottom: 0;
51
- padding: 5px;
51
+ color: #333;
52
+ margin-bottom: 0;
53
+ padding: 5px;
52
54
  }
53
55
 
54
56
  #ErrorExplanation ul li {
55
- font-size: 12px;
56
- list-style: square;
57
+ font-size: 12px;
58
+ list-style: square;
57
59
  }
58
60
  </style>
59
61
  </head>
60
62
  <body>
61
63
 
64
+ <p style="color: green"><%= flash[:notice] %></p>
65
+
62
66
  <%= @content_for_layout %>
63
67
 
64
68
  </body>
65
- </html>
69
+ </html>
@@ -12,9 +12,9 @@
12
12
  <% for column in @scaffold_class.content_columns %>
13
13
  <td><%= entry.send(column.name) %></td>
14
14
  <% end %>
15
- <td><%= link_to "Show", :action => "show#{@scaffold_suffix}", :id => entry.id %></td>
16
- <td><%= link_to "Edit", :action => "edit#{@scaffold_suffix}", :id => entry.id %></td>
17
- <td><%= link_to "Destroy", :action => "destroy#{@scaffold_suffix}", :id => entry.id %></td>
15
+ <td><%= link_to "Show", :action => "show#{@scaffold_suffix}", :id => entry %></td>
16
+ <td><%= link_to "Edit", :action => "edit#{@scaffold_suffix}", :id => entry %></td>
17
+ <td><%= link_to "Destroy", :action => "destroy#{@scaffold_suffix}", :id => entry, :confirm => "Are you sure?" %></td>
18
18
  </tr>
19
19
  <% end %>
20
20
  </table>
@@ -1,6 +1,6 @@
1
1
  <h1>New <%= @scaffold_singular_name %></h1>
2
2
 
3
3
  <%= error_messages_for(@scaffold_singular_name) %>
4
- <%= form(@scaffold_singular_name, :action => "create" + @scaffold_suffix) %>
4
+ <%= form(@scaffold_singular_name, :action => "create#{@scaffold_suffix}") %>
5
5
 
6
- <%= link_to "Back", :action => "list#{@scaffold_suffix}" %>
6
+ <%= link_to "Back", :action => "list#{@scaffold_suffix}" %>
@@ -5,5 +5,5 @@
5
5
  </p>
6
6
  <% end %>
7
7
 
8
- <%= link_to "Edit", :action => "edit#{@scaffold_suffix}", :id => instance_variable_get("@#{@scaffold_singular_name}").id %> |
8
+ <%= link_to "Edit", :action => "edit#{@scaffold_suffix}", :id => instance_variable_get("@#{@scaffold_singular_name}") %> |
9
9
  <%= link_to "Back", :action => "list#{@scaffold_suffix}" %>
@@ -1,29 +1,13 @@
1
1
  require File.dirname(__FILE__) + '/assertions'
2
2
  require File.dirname(__FILE__) + '/deprecated_assertions'
3
3
 
4
- if defined?(RAILS_ROOT)
5
- # Temporary hack for getting functional tests in Rails running under 1.8.2
6
- class Object #:nodoc:
7
- alias_method :require_without_load_path_reloading, :require
8
- def require(file_name)
9
- begin
10
- require_without_load_path_reloading(file_name)
11
- rescue Object => e
12
- ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
13
- require_without_load_path_reloading(file_name)
14
- end
15
- end
16
- end
17
- end
18
-
19
-
20
4
  module ActionController #:nodoc:
21
5
  class Base
22
6
  # Process a test request called with a +TestRequest+ object.
23
7
  def self.process_test(request)
24
8
  new.process_test(request)
25
9
  end
26
-
10
+
27
11
  def process_test(request) #:nodoc:
28
12
  process(request, TestResponse.new)
29
13
  end
@@ -32,13 +16,13 @@ module ActionController #:nodoc:
32
16
  class TestRequest < AbstractRequest #:nodoc:
33
17
  attr_accessor :cookies
34
18
  attr_accessor :query_parameters, :request_parameters, :path, :session, :env
35
- attr_accessor :host, :remote_addr
19
+ attr_accessor :host
36
20
 
37
21
  def initialize(query_parameters = nil, request_parameters = nil, session = nil)
38
22
  @query_parameters = query_parameters || {}
39
23
  @request_parameters = request_parameters || {}
40
24
  @session = session || TestSession.new
41
-
25
+
42
26
  initialize_containers
43
27
  initialize_default_values
44
28
 
@@ -47,8 +31,8 @@ module ActionController #:nodoc:
47
31
 
48
32
  def reset_session
49
33
  @session = {}
50
- end
51
-
34
+ end
35
+
52
36
  def port=(number)
53
37
  @env["SERVER_PORT"] = number.to_i
54
38
  end
@@ -57,7 +41,7 @@ module ActionController #:nodoc:
57
41
  @query_parameters.update({ "action" => action_name })
58
42
  @parameters = nil
59
43
  end
60
-
44
+
61
45
  # Used to check AbstractRequest's request_uri functionality.
62
46
  # Disables the use of @path and @request_uri so superclass can handle those.
63
47
  def set_REQUEST_URI(value)
@@ -71,6 +55,10 @@ module ActionController #:nodoc:
71
55
  @path = uri.split("?").first
72
56
  end
73
57
 
58
+ def remote_addr=(addr)
59
+ @env['REMOTE_ADDR'] = addr
60
+ end
61
+
74
62
  def request_uri
75
63
  @request_uri || super()
76
64
  end
@@ -78,27 +66,45 @@ module ActionController #:nodoc:
78
66
  def path
79
67
  @path || super()
80
68
  end
69
+
70
+ def assign_parameters(controller_path, action, parameters)
71
+ parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
72
+ extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
73
+ non_path_parameters = get? ? query_parameters : request_parameters
74
+ parameters.each do |key, value|
75
+ if extra_keys.include?(key.to_sym)
76
+ non_path_parameters[key] = value
77
+ else
78
+ path_parameters[key] = value.to_s
79
+ end
80
+ end
81
+ end
81
82
 
83
+ def recycle!
84
+ self.request_parameters = {}
85
+ self.query_parameters = {}
86
+ self.path_parameters = {}
87
+ end
82
88
 
83
89
  private
84
90
  def initialize_containers
85
91
  @env, @cookies = {}, {}
86
92
  end
87
-
93
+
88
94
  def initialize_default_values
89
95
  @host = "test.host"
90
96
  @request_uri = "/"
91
- @remote_addr, @remote_ip = "127.0.0.1"
97
+ self.remote_addr = "0.0.0.0"
92
98
  @env["SERVER_PORT"] = 80
93
99
  end
94
100
  end
95
-
101
+
96
102
  class TestResponse < AbstractResponse #:nodoc:
97
103
  # the response code of the request
98
104
  def response_code
99
105
  headers['Status'][0,3].to_i rescue 0
100
106
  end
101
-
107
+
102
108
  # was the response successful?
103
109
  def success?
104
110
  response_code == 200
@@ -113,7 +119,7 @@ module ActionController #:nodoc:
113
119
  def redirect?
114
120
  (300..399).include?(response_code)
115
121
  end
116
-
122
+
117
123
  # was there a server-side error?
118
124
  def error?
119
125
  (500..599).include?(response_code)
@@ -125,7 +131,7 @@ module ActionController #:nodoc:
125
131
  def redirect_url
126
132
  redirect? ? headers['location'] : nil
127
133
  end
128
-
134
+
129
135
  # does the redirect location match this regexp pattern?
130
136
  def redirect_url_match?( pattern )
131
137
  return false if redirect_url.nil?
@@ -134,7 +140,7 @@ module ActionController #:nodoc:
134
140
  return false if p.nil?
135
141
  p.match(redirect_url) != nil
136
142
  end
137
-
143
+
138
144
  # returns the template path of the file which was used to
139
145
  # render this response (or nil)
140
146
  def rendered_file(with_controller=false)
@@ -156,7 +162,7 @@ module ActionController #:nodoc:
156
162
  def flash
157
163
  session['flash'] || {}
158
164
  end
159
-
165
+
160
166
  # do we have a flash?
161
167
  def has_flash?
162
168
  !session['flash'].empty?
@@ -181,12 +187,12 @@ module ActionController #:nodoc:
181
187
  def template_objects
182
188
  template.assigns || {}
183
189
  end
184
-
190
+
185
191
  # does the specified template object exist?
186
192
  def has_template_object?(name=nil)
187
193
  !template_objects[name].nil?
188
194
  end
189
-
195
+
190
196
  # Returns the response cookies, converted to a Hash of (name => CGI::Cookie) pairs
191
197
  # Example:
192
198
  #
@@ -226,11 +232,11 @@ end
226
232
  def []=(key, value)
227
233
  @attributes[key] = value
228
234
  end
229
-
235
+
230
236
  def session_id
231
237
  ""
232
238
  end
233
-
239
+
234
240
  def update() end
235
241
  def close() end
236
242
  def delete() @attributes = {} end
@@ -243,18 +249,26 @@ module Test
243
249
  private
244
250
  # execute the request and set/volley the response
245
251
  def process(action, parameters = nil, session = nil, flash = nil)
252
+ @request.recycle!
253
+
254
+ # Sanity check for required instance variables so we can give an understandable error message.
255
+ %w(controller request response).each do |iv_name|
256
+ assert_not_nil instance_variable_get("@#{iv_name}"), "@#{iv_name} is nil: make sure you set it in your test's setup method."
257
+ end
258
+
246
259
  @html_document = nil
247
260
  @request.env['REQUEST_METHOD'] ||= "GET"
248
261
  @request.action = action.to_s
249
- @request.path_parameters = { :controller => @controller.class.controller_path,
250
- :action => action.to_s }
251
- @request.parameters.update(parameters) unless parameters.nil?
262
+
263
+ parameters ||= {}
264
+ @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)
265
+
252
266
  @request.session = ActionController::TestSession.new(session) unless session.nil?
253
267
  @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
254
268
  build_request_uri(action, parameters)
255
269
  @controller.process(@request, @response)
256
270
  end
257
-
271
+
258
272
  # execute the request simulating a specific http method and set/volley the response
259
273
  %w( get post put delete head ).each do |method|
260
274
  class_eval <<-EOV
@@ -275,7 +289,7 @@ module Test
275
289
  if @response.redirected_to[:controller]
276
290
  raise "Can't follow redirects outside of current controller (#{@response.redirected_to[:controller]})"
277
291
  end
278
-
292
+
279
293
  get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys)
280
294
  end
281
295
 
@@ -286,7 +300,7 @@ module Test
286
300
  @response.template.assigns[key.to_s]
287
301
  end
288
302
  end
289
-
303
+
290
304
  def session
291
305
  @response.session
292
306
  end
@@ -304,18 +318,20 @@ module Test
304
318
  end
305
319
 
306
320
  def build_request_uri(action, parameters)
307
- return if @request.env['REQUEST_URI']
308
- url = ActionController::UrlRewriter.new(@request, parameters)
309
- @request.set_REQUEST_URI(
310
- url.rewrite(@controller.send(:rewrite_options,
311
- (parameters||{}).update(:only_path => true, :action=>action))))
321
+ unless @request.env['REQUEST_URI']
322
+ options = @controller.send(:rewrite_options, parameters)
323
+ options.update(:only_path => true, :action => action)
324
+
325
+ url = ActionController::UrlRewriter.new(@request, parameters)
326
+ @request.set_REQUEST_URI(url.rewrite(options))
327
+ end
312
328
  end
313
329
 
314
330
  def html_document
315
331
  require_html_scanner
316
332
  @html_document ||= HTML::Document.new(@response.body)
317
333
  end
318
-
334
+
319
335
  def find_tag(conditions)
320
336
  html_document.find(conditions)
321
337
  end
@@ -331,6 +347,11 @@ module Test
331
347
  $:.unshift File.dirname(__FILE__) + "/vendor/html-scanner"
332
348
  require 'html/document'
333
349
  end
334
- end
350
+
351
+ def method_missing(selector, *args)
352
+ return @controller.send(selector, *args) if ActionController::Routing::NamedRoutes::Helpers.include?(selector)
353
+ return super
354
+ end
355
+ end
335
356
  end
336
357
  end