actionpack 1.12.5 → 1.13.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 (179) hide show
  1. data/CHANGELOG +517 -15
  2. data/MIT-LICENSE +1 -1
  3. data/README +18 -20
  4. data/Rakefile +7 -4
  5. data/examples/address_book_controller.rb +3 -3
  6. data/examples/blog_controller.cgi +3 -3
  7. data/examples/debate_controller.cgi +5 -5
  8. data/lib/action_controller.rb +2 -2
  9. data/lib/action_controller/assertions.rb +73 -311
  10. data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
  11. data/lib/action_controller/assertions/dom_assertions.rb +25 -0
  12. data/lib/action_controller/assertions/model_assertions.rb +12 -0
  13. data/lib/action_controller/assertions/response_assertions.rb +140 -0
  14. data/lib/action_controller/assertions/routing_assertions.rb +82 -0
  15. data/lib/action_controller/assertions/selector_assertions.rb +571 -0
  16. data/lib/action_controller/assertions/tag_assertions.rb +117 -0
  17. data/lib/action_controller/base.rb +334 -163
  18. data/lib/action_controller/benchmarking.rb +3 -6
  19. data/lib/action_controller/caching.rb +83 -22
  20. data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
  21. data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
  22. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
  23. data/lib/action_controller/cgi_process.rb +50 -27
  24. data/lib/action_controller/components.rb +21 -25
  25. data/lib/action_controller/cookies.rb +10 -9
  26. data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
  27. data/lib/action_controller/filters.rb +448 -225
  28. data/lib/action_controller/flash.rb +24 -20
  29. data/lib/action_controller/helpers.rb +2 -5
  30. data/lib/action_controller/integration.rb +40 -16
  31. data/lib/action_controller/layout.rb +11 -8
  32. data/lib/action_controller/macros/auto_complete.rb +3 -2
  33. data/lib/action_controller/macros/in_place_editing.rb +3 -2
  34. data/lib/action_controller/mime_responds.rb +41 -29
  35. data/lib/action_controller/mime_type.rb +68 -10
  36. data/lib/action_controller/pagination.rb +4 -3
  37. data/lib/action_controller/request.rb +22 -14
  38. data/lib/action_controller/rescue.rb +25 -22
  39. data/lib/action_controller/resources.rb +302 -0
  40. data/lib/action_controller/response.rb +20 -2
  41. data/lib/action_controller/response.rb.rej +17 -0
  42. data/lib/action_controller/routing.rb +1165 -567
  43. data/lib/action_controller/scaffolding.rb +30 -31
  44. data/lib/action_controller/session/active_record_store.rb +2 -0
  45. data/lib/action_controller/session/drb_store.rb +4 -0
  46. data/lib/action_controller/session/mem_cache_store.rb +4 -0
  47. data/lib/action_controller/session_management.rb +6 -9
  48. data/lib/action_controller/status_codes.rb +89 -0
  49. data/lib/action_controller/streaming.rb +6 -15
  50. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
  51. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
  52. data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
  53. data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
  54. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  55. data/lib/action_controller/test_process.rb +52 -30
  56. data/lib/action_controller/url_rewriter.rb +63 -29
  57. data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
  58. data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
  59. data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
  60. data/lib/action_controller/verification.rb +22 -11
  61. data/lib/action_pack.rb +1 -1
  62. data/lib/action_pack/version.rb +2 -2
  63. data/lib/action_view.rb +1 -1
  64. data/lib/action_view/base.rb +46 -43
  65. data/lib/action_view/compiled_templates.rb +1 -1
  66. data/lib/action_view/helpers/active_record_helper.rb +54 -17
  67. data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
  68. data/lib/action_view/helpers/capture_helper.rb +1 -1
  69. data/lib/action_view/helpers/date_helper.rb +258 -136
  70. data/lib/action_view/helpers/debug_helper.rb +1 -1
  71. data/lib/action_view/helpers/deprecated_helper.rb +34 -0
  72. data/lib/action_view/helpers/form_helper.rb +75 -35
  73. data/lib/action_view/helpers/form_options_helper.rb +7 -5
  74. data/lib/action_view/helpers/form_tag_helper.rb +44 -6
  75. data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
  76. data/lib/action_view/helpers/javascript_helper.rb +71 -10
  77. data/lib/action_view/helpers/javascripts/controls.js +41 -23
  78. data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
  79. data/lib/action_view/helpers/javascripts/effects.js +293 -163
  80. data/lib/action_view/helpers/javascripts/prototype.js +897 -389
  81. data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
  82. data/lib/action_view/helpers/number_helper.rb +111 -65
  83. data/lib/action_view/helpers/prototype_helper.rb +84 -109
  84. data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
  85. data/lib/action_view/helpers/tag_helper.rb +69 -16
  86. data/lib/action_view/helpers/text_helper.rb +149 -112
  87. data/lib/action_view/helpers/url_helper.rb +200 -107
  88. data/lib/action_view/template_error.rb +66 -42
  89. data/test/abstract_unit.rb +4 -2
  90. data/test/active_record_unit.rb +84 -56
  91. data/test/activerecord/active_record_assertions_test.rb +26 -18
  92. data/test/activerecord/active_record_store_test.rb +4 -36
  93. data/test/activerecord/pagination_test.rb +1 -6
  94. data/test/controller/action_pack_assertions_test.rb +230 -113
  95. data/test/controller/addresses_render_test.rb +2 -6
  96. data/test/controller/assert_select_test.rb +576 -0
  97. data/test/controller/base_test.rb +73 -3
  98. data/test/controller/caching_test.rb +228 -0
  99. data/test/controller/capture_test.rb +12 -10
  100. data/test/controller/cgi_test.rb +89 -12
  101. data/test/controller/components_test.rb +24 -2
  102. data/test/controller/content_type_test.rb +139 -0
  103. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  104. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  105. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  106. data/test/controller/cookie_test.rb +33 -25
  107. data/test/controller/deprecated_instance_variables_test.rb +48 -0
  108. data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
  109. data/test/controller/fake_controllers.rb +0 -1
  110. data/test/controller/filters_test.rb +301 -16
  111. data/test/controller/flash_test.rb +19 -2
  112. data/test/controller/helper_test.rb +2 -2
  113. data/test/controller/integration_test.rb +154 -0
  114. data/test/controller/layout_test.rb +115 -1
  115. data/test/controller/mime_responds_test.rb +94 -0
  116. data/test/controller/mime_type_test.rb +9 -0
  117. data/test/controller/new_render_test.rb +161 -11
  118. data/test/controller/raw_post_test.rb +52 -15
  119. data/test/controller/redirect_test.rb +27 -14
  120. data/test/controller/render_test.rb +76 -29
  121. data/test/controller/request_test.rb +55 -4
  122. data/test/controller/resources_test.rb +274 -0
  123. data/test/controller/routing_test.rb +1533 -824
  124. data/test/controller/selector_test.rb +628 -0
  125. data/test/controller/send_file_test.rb +9 -1
  126. data/test/controller/session_management_test.rb +51 -0
  127. data/test/controller/test_test.rb +113 -29
  128. data/test/controller/url_rewriter_test.rb +86 -17
  129. data/test/controller/verification_test.rb +19 -17
  130. data/test/controller/webservice_test.rb +0 -7
  131. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  132. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  133. data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
  134. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  135. data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
  136. data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
  137. data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
  138. data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
  139. data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
  140. data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
  141. data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
  142. data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
  143. data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
  144. data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
  145. data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
  146. data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
  147. data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
  148. data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
  149. data/test/fixtures/multipart/binary_file +0 -0
  150. data/test/fixtures/public/javascripts/application.js +1 -0
  151. data/test/fixtures/test/_hello.rxml +1 -0
  152. data/test/fixtures/test/hello_world_container.rxml +3 -0
  153. data/test/fixtures/topic.rb +2 -2
  154. data/test/template/active_record_helper_test.rb +83 -12
  155. data/test/template/asset_tag_helper_test.rb +75 -95
  156. data/test/template/compiled_templates_test.rb +1 -0
  157. data/test/template/date_helper_test.rb +873 -181
  158. data/test/template/deprecated_helper_test.rb +36 -0
  159. data/test/template/deprecated_instance_variables_test.rb +43 -0
  160. data/test/template/form_helper_test.rb +77 -1
  161. data/test/template/form_options_helper_test.rb +4 -0
  162. data/test/template/form_tag_helper_test.rb +66 -2
  163. data/test/template/java_script_macros_helper_test.rb +4 -1
  164. data/test/template/javascript_helper_test.rb +29 -0
  165. data/test/template/number_helper_test.rb +63 -27
  166. data/test/template/prototype_helper_test.rb +77 -34
  167. data/test/template/tag_helper_test.rb +34 -6
  168. data/test/template/text_helper_test.rb +69 -34
  169. data/test/template/url_helper_test.rb +168 -16
  170. data/test/testing_sandbox.rb +7 -22
  171. metadata +66 -20
  172. data/filler.txt +0 -50
  173. data/lib/action_controller/code_generation.rb +0 -235
  174. data/lib/action_controller/vendor/xml_simple.rb +0 -1019
  175. data/test/controller/caching_filestore.rb +0 -74
  176. data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
  177. data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
  178. data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
  179. data/test/fixtures/dont_load.rb +0 -3
@@ -34,15 +34,36 @@ class TestController < ActionController::Base
34
34
  def render_action_hello_world_with_symbol
35
35
  render_action :hello_world
36
36
  end
37
-
37
+
38
38
  def render_text_hello_world
39
39
  render_text "hello world"
40
40
  end
41
41
 
42
+ def render_json_hello_world
43
+ render_json({:hello => 'world'}.to_json)
44
+ end
45
+
46
+ def render_json_hello_world_with_callback
47
+ render_json({:hello => 'world'}.to_json, 'alert')
48
+ end
49
+
50
+ def render_symbol_json
51
+ render :json => {:hello => 'world'}.to_json
52
+ end
53
+
42
54
  def render_custom_code
43
55
  render_text "hello world", "404 Moved"
44
56
  end
45
-
57
+
58
+ def render_text_appendix
59
+ render_text "hello world"
60
+ render_text ", goodbye!", "404 Not Found", true
61
+ end
62
+
63
+ def render_nothing_with_appendix
64
+ render_text "appended", nil, true
65
+ end
66
+
46
67
  def render_xml_hello
47
68
  @name = "David"
48
69
  render "test/hello"
@@ -55,11 +76,15 @@ class TestController < ActionController::Base
55
76
  def layout_test
56
77
  render_action "hello_world"
57
78
  end
58
-
79
+
59
80
  def builder_layout_test
60
81
  render_action "hello"
61
82
  end
62
83
 
84
+ def builder_partial_test
85
+ render_action "hello_world_container"
86
+ end
87
+
63
88
  def partials_list
64
89
  @test_unchanged = 'hello'
65
90
  @customers = [ Customer.new("david"), Customer.new("mary") ]
@@ -74,7 +99,7 @@ class TestController < ActionController::Base
74
99
  @customers = [ Customer.new("david"), Customer.new("mary") ]
75
100
  render_text "How's there? #{render_to_string("test/list")}"
76
101
  end
77
-
102
+
78
103
  def accessing_params_in_template
79
104
  render_template "Hello: <%= params[:name] %>"
80
105
  end
@@ -84,7 +109,7 @@ class TestController < ActionController::Base
84
109
  render :inline => "<%= 'Goodbye, ' + local_name %>",
85
110
  :locals => { :local_name => name }
86
111
  end
87
-
112
+
88
113
  def accessing_local_assigns_in_inline_template_with_string_keys
89
114
  name = params[:local_name]
90
115
  ActionView::Base.local_assigns_support_string_keys = true
@@ -98,12 +123,13 @@ class TestController < ActionController::Base
98
123
  end
99
124
 
100
125
  def rescue_action(e) raise end
101
-
126
+
102
127
  private
103
128
  def determine_layout
104
- case action_name
129
+ case action_name
105
130
  when "layout_test": "layouts/standard"
106
131
  when "builder_layout_test": "layouts/builder"
132
+ when "render_symbol_json": "layouts/standard" # to make sure layouts don't interfere
107
133
  end
108
134
  end
109
135
  end
@@ -127,7 +153,7 @@ class RenderTest < Test::Unit::TestCase
127
153
  end
128
154
 
129
155
  def test_do_with_render
130
- get :render_hello_world
156
+ assert_deprecated_render { get :render_hello_world }
131
157
  assert_template "test/hello_world"
132
158
  end
133
159
 
@@ -151,11 +177,41 @@ class RenderTest < Test::Unit::TestCase
151
177
  assert_equal "hello world", @response.body
152
178
  end
153
179
 
180
+ def test_do_with_render_json
181
+ get :render_json_hello_world
182
+ assert_equal '{hello: "world"}', @response.body
183
+ assert_equal 'application/json', @response.content_type
184
+ end
185
+
186
+ def test_do_with_render_json_with_callback
187
+ get :render_json_hello_world_with_callback
188
+ assert_equal 'alert({hello: "world"})', @response.body
189
+ assert_equal 'application/json', @response.content_type
190
+ end
191
+
192
+ def test_do_with_render_symbol_json
193
+ get :render_symbol_json
194
+ assert_equal '{hello: "world"}', @response.body
195
+ assert_equal 'application/json', @response.content_type
196
+ end
197
+
154
198
  def test_do_with_render_custom_code
155
199
  get :render_custom_code
156
200
  assert_response 404
157
201
  end
158
202
 
203
+ def test_do_with_render_text_appendix
204
+ get :render_text_appendix
205
+ assert_response 404
206
+ assert_equal 'hello world, goodbye!', @response.body
207
+ end
208
+
209
+ def test_do_with_render_nothing_with_appendix
210
+ get :render_nothing_with_appendix
211
+ assert_response 200
212
+ assert_equal 'appended', @response.body
213
+ end
214
+
159
215
  def test_attempt_to_access_object_method
160
216
  assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
161
217
  end
@@ -164,27 +220,8 @@ class RenderTest < Test::Unit::TestCase
164
220
  assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
165
221
  end
166
222
 
167
- def test_access_to_request_in_view
168
- view_internals_old_value = ActionController::Base.view_controller_internals
169
-
170
- ActionController::Base.view_controller_internals = false
171
- ActionController::Base.protected_variables_cache = nil
172
-
173
- get :hello_world
174
- assert_nil assigns["request"]
175
-
176
- ActionController::Base.view_controller_internals = true
177
- ActionController::Base.protected_variables_cache = nil
178
-
179
- get :hello_world
180
- assert_kind_of ActionController::AbstractRequest, assigns["request"]
181
-
182
- ActionController::Base.view_controller_internals = view_internals_old_value
183
- ActionController::Base.protected_variables_cache = nil
184
- end
185
-
186
223
  def test_render_xml
187
- get :render_xml_hello
224
+ assert_deprecated_render { get :render_xml_hello }
188
225
  assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
189
226
  end
190
227
 
@@ -193,6 +230,11 @@ class RenderTest < Test::Unit::TestCase
193
230
  assert_equal "<p>This is grand!</p>\n", @response.body
194
231
  end
195
232
 
233
+ def test_render_xml_with_partial
234
+ get :builder_partial_test
235
+ assert_equal "<test>\n <hello/>\n</test>\n", @response.body
236
+ end
237
+
196
238
  def test_layout_rendering
197
239
  get :layout_test
198
240
  assert_equal "<html>Hello world!</html>", @response.body
@@ -238,9 +280,14 @@ class RenderTest < Test::Unit::TestCase
238
280
  get :accessing_local_assigns_in_inline_template, :local_name => "Local David"
239
281
  assert_equal "Goodbye, Local David", @response.body
240
282
  end
241
-
283
+
242
284
  def test_accessing_local_assigns_in_inline_template_with_string_keys
243
285
  get :accessing_local_assigns_in_inline_template_with_string_keys, :local_name => "Local David"
244
286
  assert_equal "Goodbye, Local David", @response.body
245
287
  end
288
+
289
+ protected
290
+ def assert_deprecated_render(&block)
291
+ assert_deprecated(/render/, &block)
292
+ end
246
293
  end
@@ -174,39 +174,55 @@ class RequestTest < Test::Unit::TestCase
174
174
  assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
175
175
  assert_equal "/path/of/some/uri", @request.path
176
176
 
177
+ @request.set_REQUEST_URI nil
177
178
  @request.relative_url_root = nil
178
179
  @request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1"
179
180
  @request.env['SCRIPT_NAME'] = "/path/dispatch.rb"
180
181
  assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
181
182
  assert_equal "/of/some/uri", @request.path
182
183
 
184
+ @request.set_REQUEST_URI nil
183
185
  @request.relative_url_root = nil
184
186
  @request.env['PATH_INFO'] = "/path/of/some/uri"
185
187
  @request.env['SCRIPT_NAME'] = nil
186
188
  assert_equal "/path/of/some/uri", @request.request_uri
187
189
  assert_equal "/path/of/some/uri", @request.path
188
190
 
191
+ @request.set_REQUEST_URI nil
189
192
  @request.relative_url_root = nil
190
193
  @request.env['PATH_INFO'] = "/"
191
194
  assert_equal "/", @request.request_uri
192
195
  assert_equal "/", @request.path
193
196
 
197
+ @request.set_REQUEST_URI nil
194
198
  @request.relative_url_root = nil
195
199
  @request.env['PATH_INFO'] = "/?m=b"
196
200
  assert_equal "/?m=b", @request.request_uri
197
201
  assert_equal "/", @request.path
198
-
202
+
203
+ @request.set_REQUEST_URI nil
199
204
  @request.relative_url_root = nil
200
205
  @request.env['PATH_INFO'] = "/"
201
206
  @request.env['SCRIPT_NAME'] = "/dispatch.cgi"
202
207
  assert_equal "/", @request.request_uri
203
- assert_equal "/", @request.path
208
+ assert_equal "/", @request.path
204
209
 
210
+ @request.set_REQUEST_URI nil
205
211
  @request.relative_url_root = nil
206
212
  @request.env['PATH_INFO'] = "/hieraki/"
207
213
  @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
208
214
  assert_equal "/hieraki/", @request.request_uri
209
- assert_equal "/", @request.path
215
+ assert_equal "/", @request.path
216
+
217
+ @request.set_REQUEST_URI '/hieraki/dispatch.cgi'
218
+ @request.relative_url_root = '/hieraki'
219
+ assert_equal "/dispatch.cgi", @request.path
220
+ @request.relative_url_root = nil
221
+
222
+ @request.set_REQUEST_URI '/hieraki/dispatch.cgi'
223
+ @request.relative_url_root = '/foo'
224
+ assert_equal "/hieraki/dispatch.cgi", @request.path
225
+ @request.relative_url_root = nil
210
226
 
211
227
  # This test ensures that Rails uses REQUEST_URI over PATH_INFO
212
228
  @request.relative_url_root = nil
@@ -216,7 +232,7 @@ class RequestTest < Test::Unit::TestCase
216
232
  assert_equal "/some/path", @request.request_uri
217
233
  assert_equal "/some/path", @request.path
218
234
  end
219
-
235
+
220
236
 
221
237
  def test_host_with_port
222
238
  @request.host = "rubyonrails.org"
@@ -262,5 +278,40 @@ class RequestTest < Test::Unit::TestCase
262
278
  @request.env['HTTP_X_FORWARDED_PROTO'] = 'https'
263
279
  assert @request.ssl?
264
280
  end
281
+
282
+ def test_symbolized_request_methods
283
+ [:get, :post, :put, :delete].each do |method|
284
+ set_request_method_to method
285
+ assert_equal method, @request.method
286
+ end
287
+ end
288
+
289
+ def test_allow_method_hacking_on_post
290
+ set_request_method_to :post
291
+ [:get, :put, :delete].each do |method|
292
+ @request.instance_eval { @parameters = { :_method => method } ; @request_method = nil }
293
+ assert_equal method, @request.method
294
+ end
295
+ end
296
+
297
+ def test_restrict_method_hacking
298
+ @request.instance_eval { @parameters = { :_method => 'put' } }
299
+ [:get, :put, :delete].each do |method|
300
+ set_request_method_to method
301
+ assert_equal method, @request.method
302
+ end
303
+ end
265
304
 
305
+ def test_head_masquarading_as_get
306
+ set_request_method_to :head
307
+ assert_equal :get, @request.method
308
+ assert @request.get?
309
+ assert @request.head?
310
+ end
311
+
312
+ protected
313
+ def set_request_method_to(method)
314
+ @request.env['REQUEST_METHOD'] = method.to_s.upcase
315
+ @request.instance_eval { @request_method = nil }
316
+ end
266
317
  end
@@ -0,0 +1,274 @@
1
+ require File.dirname(__FILE__) + '/../abstract_unit'
2
+
3
+ class ResourcesController < ActionController::Base
4
+ def index() render :nothing => true end
5
+ def rescue_action(e) raise e end
6
+ end
7
+
8
+ class ThreadsController < ResourcesController; end
9
+ class MessagesController < ResourcesController; end
10
+ class CommentsController < ResourcesController; end
11
+
12
+
13
+ class ResourcesTest < Test::Unit::TestCase
14
+ def test_should_arrange_actions
15
+ resource = ActionController::Resources::Resource.new(:messages,
16
+ :collection => { :rss => :get, :reorder => :post, :csv => :post },
17
+ :member => { :rss => :get, :atom => :get, :upload => :post, :fix => :post },
18
+ :new => { :preview => :get, :draft => :get })
19
+
20
+ assert_resource_methods [:rss], resource, :collection, :get
21
+ assert_resource_methods [:csv, :reorder], resource, :collection, :post
22
+ assert_resource_methods [:edit, :rss, :atom], resource, :member, :get
23
+ assert_resource_methods [:upload, :fix], resource, :member, :post
24
+ assert_resource_methods [:new, :preview, :draft], resource, :new, :get
25
+ end
26
+
27
+ def test_default_restful_routes
28
+ with_restful_routing :messages do
29
+ assert_simply_restful_for :messages
30
+ end
31
+ end
32
+
33
+ def test_multiple_default_restful_routes
34
+ with_restful_routing :messages, :comments do
35
+ assert_simply_restful_for :messages
36
+ assert_simply_restful_for :comments
37
+ end
38
+ end
39
+
40
+ def test_with_path_prefix
41
+ with_restful_routing :messages, :path_prefix => '/thread/:thread_id' do
42
+ assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
43
+ end
44
+ end
45
+
46
+ def test_multile_with_path_prefix
47
+ with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do
48
+ assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
49
+ assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
50
+ end
51
+ end
52
+
53
+ def test_with_name_prefix
54
+ with_restful_routing :messages, :name_prefix => 'post_' do
55
+ assert_simply_restful_for :messages, :name_prefix => 'post_'
56
+ end
57
+ end
58
+
59
+ def test_with_collection_action
60
+ rss_options = {:action => 'rss'}
61
+ rss_path = "/messages;rss"
62
+ actions = { 'a' => :put, 'b' => :post, 'c' => :delete }
63
+
64
+ with_restful_routing :messages, :collection => { :rss => :get }.merge(actions) do
65
+ assert_restful_routes_for :messages do |options|
66
+ assert_routing rss_path, options.merge(rss_options)
67
+
68
+ actions.each do |action, method|
69
+ assert_recognizes(options.merge(:action => action), :path => "/messages;#{action}", :method => method)
70
+ end
71
+ end
72
+
73
+ assert_restful_named_routes_for :messages do |options|
74
+ assert_named_route rss_path, :rss_messages_path, rss_options
75
+ actions.keys.each do |action|
76
+ assert_named_route "/messages;#{action}", "#{action}_messages_path", :action => action
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def test_with_member_action
83
+ [:put, :post].each do |method|
84
+ with_restful_routing :messages, :member => { :mark => method } do
85
+ mark_options = {:action => 'mark', :id => '1'}
86
+ mark_path = "/messages/1;mark"
87
+ assert_restful_routes_for :messages do |options|
88
+ assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method)
89
+ end
90
+
91
+ assert_restful_named_routes_for :messages do |options|
92
+ assert_named_route mark_path, :mark_message_path, mark_options
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def test_with_two_member_actions_with_same_method
99
+ [:put, :post].each do |method|
100
+ with_restful_routing :messages, :member => { :mark => method, :unmark => method } do
101
+ %w(mark unmark).each do |action|
102
+ action_options = {:action => action, :id => '1'}
103
+ action_path = "/messages/1;#{action}"
104
+ assert_restful_routes_for :messages do |options|
105
+ assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
106
+ end
107
+
108
+ assert_restful_named_routes_for :messages do |options|
109
+ assert_named_route action_path, "#{action}_message_path".to_sym, action_options
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+
117
+ def test_with_new_action
118
+ with_restful_routing :messages, :new => { :preview => :post } do
119
+ preview_options = {:action => 'preview'}
120
+ preview_path = "/messages/new;preview"
121
+ assert_restful_routes_for :messages do |options|
122
+ assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
123
+ end
124
+
125
+ assert_restful_named_routes_for :messages do |options|
126
+ assert_named_route preview_path, :preview_new_message_path, preview_options
127
+ end
128
+ end
129
+ end
130
+
131
+ def test_override_new_method
132
+ with_restful_routing :messages do
133
+ assert_restful_routes_for :messages do |options|
134
+ assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get)
135
+ assert_raises(ActionController::RoutingError) do
136
+ ActionController::Routing::Routes.recognize_path("/messages/new", :method => :post)
137
+ end
138
+ end
139
+ end
140
+
141
+ with_restful_routing :messages, :new => { :new => :any } do
142
+ assert_restful_routes_for :messages do |options|
143
+ assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :post)
144
+ assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get)
145
+ end
146
+ end
147
+ end
148
+
149
+ def test_nested_restful_routes
150
+ with_routing do |set|
151
+ set.draw do |map|
152
+ map.resources :threads do |map|
153
+ map.resources :messages do |map|
154
+ map.resources :comments
155
+ end
156
+ end
157
+ end
158
+
159
+ assert_simply_restful_for :threads
160
+ assert_simply_restful_for :messages,
161
+ :path_prefix => 'threads/1/',
162
+ :options => { :thread_id => '1' }
163
+ assert_simply_restful_for :comments,
164
+ :path_prefix => 'threads/1/messages/2/',
165
+ :options => { :thread_id => '1', :message_id => '2' }
166
+ end
167
+ end
168
+
169
+ def test_restful_routes_dont_generate_duplicates
170
+ with_restful_routing :messages do
171
+ routes = ActionController::Routing::Routes.routes
172
+ routes.each do |route|
173
+ routes.each do |r|
174
+ next if route === r # skip the comparison instance
175
+ assert distinct_routes?(route, r), "Duplicate Route: #{route}"
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ protected
182
+ def with_restful_routing(*args)
183
+ with_routing do |set|
184
+ set.draw { |map| map.resources(*args) }
185
+ yield
186
+ end
187
+ end
188
+
189
+ # runs assert_restful_routes_for and assert_restful_named_routes for on the controller_name and options, without passing a block.
190
+ def assert_simply_restful_for(controller_name, options = {})
191
+ assert_restful_routes_for controller_name, options
192
+ assert_restful_named_routes_for controller_name, options
193
+ end
194
+
195
+ def assert_restful_routes_for(controller_name, options = {})
196
+ (options[:options] ||= {})[:controller] = controller_name.to_s
197
+
198
+ collection_path = "/#{options[:path_prefix]}#{controller_name}"
199
+ member_path = "#{collection_path}/1"
200
+ new_path = "#{collection_path}/new"
201
+
202
+ with_options(options[:options]) do |controller|
203
+ controller.assert_routing collection_path, :action => 'index'
204
+ controller.assert_routing "#{collection_path}.xml" , :action => 'index', :format => 'xml'
205
+ controller.assert_routing new_path, :action => 'new'
206
+ controller.assert_routing member_path, :action => 'show', :id => '1'
207
+ controller.assert_routing "#{member_path};edit", :action => 'edit', :id => '1'
208
+ controller.assert_routing "#{member_path}.xml", :action => 'show', :id => '1', :format => 'xml'
209
+ end
210
+
211
+ assert_recognizes(
212
+ options[:options].merge(:action => 'create'),
213
+ :path => collection_path, :method => :post)
214
+
215
+ assert_recognizes(
216
+ options[:options].merge(:action => 'update', :id => '1'),
217
+ :path => member_path, :method => :put)
218
+
219
+ assert_recognizes(
220
+ options[:options].merge(:action => 'destroy', :id => '1'),
221
+ :path => member_path, :method => :delete)
222
+
223
+ yield options[:options] if block_given?
224
+ end
225
+
226
+ # test named routes like foo_path and foos_path map to the correct options.
227
+ def assert_restful_named_routes_for(controller_name, singular_name = nil, options = {})
228
+ if singular_name.is_a?(Hash)
229
+ options = singular_name
230
+ singular_name = nil
231
+ end
232
+ singular_name ||= controller_name.to_s.singularize
233
+ (options[:options] ||= {})[:controller] = controller_name.to_s
234
+ @controller = "#{controller_name.to_s.camelize}Controller".constantize.new
235
+ @request = ActionController::TestRequest.new
236
+ @response = ActionController::TestResponse.new
237
+ get :index, options[:options]
238
+ options[:options].delete :action
239
+
240
+ full_prefix = "/#{options[:path_prefix]}#{controller_name}"
241
+ name_prefix = options[:name_prefix]
242
+
243
+ assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options]
244
+ assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge(:format => 'xml')
245
+ assert_named_route "#{full_prefix}/new", "#{name_prefix}new_#{singular_name}_path", options[:options]
246
+ assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
247
+ assert_named_route "#{full_prefix}/1;edit", "#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1')
248
+ assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:format => 'xml', :id => '1')
249
+ yield options[:options] if block_given?
250
+ end
251
+
252
+ def assert_named_route(expected, route, options)
253
+ actual = @controller.send(route, options) rescue $!.class.name
254
+ assert_equal expected, actual, "Error on route: #{route}(#{options.inspect})"
255
+ end
256
+
257
+ def assert_resource_methods(expected, resource, action_method, method)
258
+ assert_equal expected.length, resource.send("#{action_method}_methods")[method].size, "#{resource.send("#{action_method}_methods")[method].inspect}"
259
+ expected.each do |action|
260
+ assert resource.send("#{action_method}_methods")[method].include?(action),
261
+ "#{method} not in #{action_method} methods: #{resource.send("#{action_method}_methods")[method].inspect}"
262
+ end
263
+ end
264
+
265
+ def distinct_routes? (r1, r2)
266
+ if r1.conditions == r2.conditions and r1.requirements == r2.requirements then
267
+ if r1.segments.collect(&:to_s) == r2.segments.collect(&:to_s) then
268
+ return false
269
+ end
270
+ end
271
+ true
272
+ end
273
+
274
+ end