actionpack 2.1.2 → 2.2.2

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 (200) hide show
  1. data/CHANGELOG +223 -7
  2. data/README +6 -12
  3. data/Rakefile +11 -11
  4. data/lib/action_controller.rb +9 -9
  5. data/lib/action_controller/assertions/response_assertions.rb +29 -78
  6. data/lib/action_controller/assertions/routing_assertions.rb +33 -33
  7. data/lib/action_controller/assertions/selector_assertions.rb +9 -5
  8. data/lib/action_controller/base.rb +227 -161
  9. data/lib/action_controller/benchmarking.rb +37 -24
  10. data/lib/action_controller/caching/actions.rb +53 -21
  11. data/lib/action_controller/caching/fragments.rb +10 -36
  12. data/lib/action_controller/caching/sweeping.rb +3 -3
  13. data/lib/action_controller/cgi_ext/session.rb +2 -22
  14. data/lib/action_controller/cgi_process.rb +8 -46
  15. data/lib/action_controller/components.rb +4 -1
  16. data/lib/action_controller/cookies.rb +10 -0
  17. data/lib/action_controller/dispatcher.rb +49 -15
  18. data/lib/action_controller/filters.rb +48 -10
  19. data/lib/action_controller/headers.rb +16 -14
  20. data/lib/action_controller/helpers.rb +2 -2
  21. data/lib/action_controller/http_authentication.rb +1 -1
  22. data/lib/action_controller/integration.rb +57 -60
  23. data/lib/action_controller/layout.rb +27 -53
  24. data/lib/action_controller/mime_responds.rb +5 -1
  25. data/lib/action_controller/mime_type.rb +64 -42
  26. data/lib/action_controller/mime_types.rb +2 -1
  27. data/lib/action_controller/performance_test.rb +16 -0
  28. data/lib/action_controller/polymorphic_routes.rb +16 -9
  29. data/lib/action_controller/rack_process.rb +303 -0
  30. data/lib/action_controller/request.rb +205 -97
  31. data/lib/action_controller/request_forgery_protection.rb +2 -2
  32. data/lib/action_controller/request_profiler.rb +0 -0
  33. data/lib/action_controller/rescue.rb +20 -115
  34. data/lib/action_controller/resources.rb +186 -83
  35. data/lib/action_controller/response.rb +140 -26
  36. data/lib/action_controller/routing.rb +28 -30
  37. data/lib/action_controller/routing/builder.rb +45 -54
  38. data/lib/action_controller/routing/optimisations.rb +31 -21
  39. data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
  40. data/lib/action_controller/routing/route.rb +162 -147
  41. data/lib/action_controller/routing/route_set.rb +8 -7
  42. data/lib/action_controller/routing/routing_ext.rb +4 -1
  43. data/lib/action_controller/routing/segments.rb +50 -21
  44. data/lib/action_controller/session/cookie_store.rb +3 -2
  45. data/lib/action_controller/session/drb_server.rb +7 -7
  46. data/lib/action_controller/session_management.rb +6 -2
  47. data/lib/action_controller/streaming.rb +15 -8
  48. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  49. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  50. data/lib/action_controller/test_case.rb +66 -2
  51. data/lib/action_controller/test_process.rb +71 -66
  52. data/lib/action_controller/translation.rb +13 -0
  53. data/lib/action_controller/url_rewriter.rb +90 -13
  54. data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
  55. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
  56. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
  57. data/lib/action_controller/verification.rb +2 -2
  58. data/lib/action_pack/version.rb +1 -1
  59. data/lib/action_view.rb +19 -11
  60. data/lib/action_view/base.rb +184 -150
  61. data/lib/action_view/helpers.rb +38 -0
  62. data/lib/action_view/helpers/active_record_helper.rb +56 -27
  63. data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
  64. data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
  65. data/lib/action_view/helpers/benchmark_helper.rb +3 -3
  66. data/lib/action_view/helpers/cache_helper.rb +1 -2
  67. data/lib/action_view/helpers/capture_helper.rb +19 -44
  68. data/lib/action_view/helpers/date_helper.rb +486 -296
  69. data/lib/action_view/helpers/debug_helper.rb +20 -13
  70. data/lib/action_view/helpers/form_helper.rb +71 -30
  71. data/lib/action_view/helpers/form_options_helper.rb +15 -85
  72. data/lib/action_view/helpers/form_tag_helper.rb +61 -38
  73. data/lib/action_view/helpers/javascript_helper.rb +80 -89
  74. data/lib/action_view/helpers/number_helper.rb +179 -74
  75. data/lib/action_view/helpers/prototype_helper.rb +216 -201
  76. data/lib/action_view/helpers/record_tag_helper.rb +4 -5
  77. data/lib/action_view/helpers/sanitize_helper.rb +65 -33
  78. data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
  79. data/lib/action_view/helpers/tag_helper.rb +39 -22
  80. data/lib/action_view/helpers/text_helper.rb +212 -118
  81. data/lib/action_view/helpers/translation_helper.rb +21 -0
  82. data/lib/action_view/helpers/url_helper.rb +100 -58
  83. data/lib/action_view/inline_template.rb +13 -14
  84. data/lib/action_view/locale/en.yml +91 -0
  85. data/lib/action_view/partials.rb +100 -55
  86. data/lib/action_view/paths.rb +125 -0
  87. data/lib/action_view/renderable.rb +102 -0
  88. data/lib/action_view/renderable_partial.rb +48 -0
  89. data/lib/action_view/template.rb +90 -101
  90. data/lib/action_view/template_error.rb +11 -21
  91. data/lib/action_view/template_handler.rb +8 -28
  92. data/lib/action_view/template_handlers.rb +45 -0
  93. data/lib/action_view/template_handlers/builder.rb +5 -15
  94. data/lib/action_view/template_handlers/erb.rb +9 -6
  95. data/lib/action_view/template_handlers/rjs.rb +2 -17
  96. data/lib/action_view/test_case.rb +7 -4
  97. data/test/abstract_unit.rb +4 -1
  98. data/test/active_record_unit.rb +28 -30
  99. data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
  100. data/test/controller/action_pack_assertions_test.rb +8 -37
  101. data/test/controller/addresses_render_test.rb +0 -3
  102. data/test/controller/assert_select_test.rb +51 -24
  103. data/test/controller/base_test.rb +4 -4
  104. data/test/controller/caching_test.rb +136 -66
  105. data/test/controller/capture_test.rb +1 -21
  106. data/test/controller/cgi_test.rb +157 -10
  107. data/test/controller/components_test.rb +41 -25
  108. data/test/controller/content_type_test.rb +49 -17
  109. data/test/controller/cookie_test.rb +1 -1
  110. data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
  111. data/test/controller/dispatcher_test.rb +9 -1
  112. data/test/controller/filter_params_test.rb +2 -2
  113. data/test/controller/filters_test.rb +13 -13
  114. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  115. data/test/controller/html-scanner/node_test.rb +21 -0
  116. data/test/controller/html-scanner/sanitizer_test.rb +14 -0
  117. data/test/controller/integration_test.rb +167 -6
  118. data/test/controller/layout_test.rb +11 -68
  119. data/test/controller/logging_test.rb +46 -0
  120. data/test/controller/mime_responds_test.rb +61 -59
  121. data/test/controller/mime_type_test.rb +6 -6
  122. data/test/controller/polymorphic_routes_test.rb +37 -2
  123. data/test/controller/rack_test.rb +323 -0
  124. data/test/controller/redirect_test.rb +72 -71
  125. data/test/controller/render_test.rb +1120 -108
  126. data/test/controller/request_forgery_protection_test.rb +66 -52
  127. data/test/controller/request_test.rb +103 -146
  128. data/test/controller/rescue_test.rb +20 -24
  129. data/test/controller/resources_test.rb +408 -25
  130. data/test/controller/routing_test.rb +1774 -1774
  131. data/test/controller/send_file_test.rb +0 -4
  132. data/test/controller/session/cookie_store_test.rb +53 -1
  133. data/test/controller/test_test.rb +15 -37
  134. data/test/controller/translation_test.rb +26 -0
  135. data/test/controller/url_rewriter_test.rb +27 -28
  136. data/test/controller/view_paths_test.rb +48 -47
  137. data/test/fixtures/_top_level_partial.html.erb +1 -0
  138. data/test/fixtures/_top_level_partial_only.erb +1 -0
  139. data/test/fixtures/developers/_developer.erb +1 -0
  140. data/test/fixtures/fun/games/_game.erb +1 -0
  141. data/test/fixtures/fun/serious/games/_game.erb +1 -0
  142. data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
  143. data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
  144. data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
  145. data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
  146. data/test/fixtures/layouts/_column.html.erb +2 -0
  147. data/test/fixtures/projects/_project.erb +1 -0
  148. data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
  149. data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
  150. data/test/fixtures/replies/_reply.erb +1 -0
  151. data/test/fixtures/test/_counter.html.erb +1 -0
  152. data/test/fixtures/test/_customer.erb +1 -1
  153. data/test/fixtures/test/_customer_with_var.erb +1 -0
  154. data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
  155. data/test/fixtures/test/_local_inspector.html.erb +1 -0
  156. data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
  157. data/test/fixtures/test/hello.builder +1 -1
  158. data/test/fixtures/test/hyphen-ated.erb +1 -0
  159. data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
  160. data/test/fixtures/test/nested_layout.erb +3 -0
  161. data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
  162. data/test/fixtures/test/sub_template_raise.html.erb +1 -0
  163. data/test/fixtures/test/template.erb +1 -0
  164. data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
  165. data/test/template/active_record_helper_i18n_test.rb +46 -0
  166. data/test/template/active_record_helper_test.rb +24 -24
  167. data/test/template/asset_tag_helper_test.rb +161 -29
  168. data/test/template/atom_feed_helper_test.rb +114 -5
  169. data/test/template/compiled_templates_test.rb +59 -0
  170. data/test/template/date_helper_i18n_test.rb +113 -0
  171. data/test/template/date_helper_test.rb +403 -109
  172. data/test/template/form_helper_test.rb +213 -154
  173. data/test/template/form_options_helper_test.rb +249 -897
  174. data/test/template/form_tag_helper_test.rb +80 -32
  175. data/test/template/javascript_helper_test.rb +17 -18
  176. data/test/template/number_helper_i18n_test.rb +54 -0
  177. data/test/template/number_helper_test.rb +43 -13
  178. data/test/template/prototype_helper_test.rb +101 -84
  179. data/test/template/record_tag_helper_test.rb +24 -20
  180. data/test/template/render_test.rb +193 -0
  181. data/test/template/sanitize_helper_test.rb +3 -3
  182. data/test/template/tag_helper_test.rb +34 -14
  183. data/test/template/text_helper_test.rb +83 -9
  184. data/test/template/translation_helper_test.rb +28 -0
  185. data/test/template/url_helper_test.rb +55 -18
  186. metadata +57 -18
  187. data/lib/action_view/helpers/javascripts/controls.js +0 -963
  188. data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
  189. data/lib/action_view/helpers/javascripts/effects.js +0 -1120
  190. data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
  191. data/lib/action_view/partial_template.rb +0 -70
  192. data/lib/action_view/template_finder.rb +0 -177
  193. data/lib/action_view/template_handlers/compilable.rb +0 -128
  194. data/test/controller/custom_handler_test.rb +0 -45
  195. data/test/controller/new_render_test.rb +0 -945
  196. data/test/fixtures/test/block_content_for.erb +0 -2
  197. data/test/fixtures/test/erb_content_for.erb +0 -2
  198. data/test/template/deprecated_erb_variable_test.rb +0 -9
  199. data/test/template/template_finder_test.rb +0 -73
  200. data/test/template/template_object_test.rb +0 -95
@@ -62,6 +62,11 @@ class RescueController < ActionController::Base
62
62
  render :text => exception.message
63
63
  end
64
64
 
65
+ # This is a Dispatcher exception and should be in ApplicationController.
66
+ rescue_from ActionController::RoutingError do
67
+ render :text => 'no way'
68
+ end
69
+
65
70
  def raises
66
71
  render :text => 'already rendered'
67
72
  raise "don't panic!"
@@ -70,7 +75,7 @@ class RescueController < ActionController::Base
70
75
  def method_not_allowed
71
76
  raise ActionController::MethodNotAllowed.new(:get, :head, :put)
72
77
  end
73
-
78
+
74
79
  def not_implemented
75
80
  raise ActionController::NotImplemented.new(:get, :put)
76
81
  end
@@ -102,7 +107,7 @@ class RescueController < ActionController::Base
102
107
  def record_invalid_raise_as_string
103
108
  raise RecordInvalidToRescueAsString
104
109
  end
105
-
110
+
106
111
  def bad_gateway
107
112
  raise BadGateway
108
113
  end
@@ -130,18 +135,19 @@ class RescueController < ActionController::Base
130
135
  end
131
136
  end
132
137
 
133
- class RescueTest < Test::Unit::TestCase
138
+ class RescueControllerTest < ActionController::TestCase
134
139
  FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze
135
140
 
136
- def setup
137
- @controller = RescueController.new
138
- @request = ActionController::TestRequest.new
139
- @response = ActionController::TestResponse.new
141
+ setup :set_all_requests_local
142
+ setup :populate_exception_object
140
143
 
144
+ def set_all_requests_local
141
145
  RescueController.consider_all_requests_local = true
142
146
  @request.remote_addr = '1.2.3.4'
143
147
  @request.host = 'example.com'
148
+ end
144
149
 
150
+ def populate_exception_object
145
151
  begin
146
152
  raise 'foo'
147
153
  rescue => @exception
@@ -302,7 +308,7 @@ class RescueTest < Test::Unit::TestCase
302
308
  assert_nil @controller.send(:clean_backtrace, Exception.new)
303
309
  end
304
310
  end
305
-
311
+
306
312
  def test_not_implemented
307
313
  with_all_requests_local false do
308
314
  with_rails_public_path(".") do
@@ -378,6 +384,10 @@ class RescueTest < Test::Unit::TestCase
378
384
  assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body
379
385
  end
380
386
 
387
+ def test_rescue_dispatcher_exceptions
388
+ RescueController.process_with_exception(@request, @response, ActionController::RoutingError.new("Route not found"))
389
+ assert_equal "no way", @response.body
390
+ end
381
391
 
382
392
  protected
383
393
  def with_all_requests_local(local = true)
@@ -454,14 +464,7 @@ class ExceptionInheritanceRescueController < ActionController::Base
454
464
  end
455
465
  end
456
466
 
457
- class ExceptionInheritanceRescueTest < Test::Unit::TestCase
458
-
459
- def setup
460
- @controller = ExceptionInheritanceRescueController.new
461
- @request = ActionController::TestRequest.new
462
- @response = ActionController::TestResponse.new
463
- end
464
-
467
+ class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
465
468
  def test_bottom_first
466
469
  get :raise_grandchild_exception
467
470
  assert_response :no_content
@@ -491,14 +494,7 @@ class ControllerInheritanceRescueController < ExceptionInheritanceRescueControll
491
494
  end
492
495
  end
493
496
 
494
- class ControllerInheritanceRescueControllerTest < Test::Unit::TestCase
495
-
496
- def setup
497
- @controller = ControllerInheritanceRescueController.new
498
- @request = ActionController::TestRequest.new
499
- @response = ActionController::TestResponse.new
500
- end
501
-
497
+ class ControllerInheritanceRescueControllerTest < ActionController::TestCase
502
498
  def test_first_exception_in_child_controller
503
499
  get :raise_first_exception_in_child_controller
504
500
  assert_response :gone
@@ -14,6 +14,8 @@ class LogosController < ResourcesController; end
14
14
 
15
15
  class AccountsController < ResourcesController; end
16
16
  class AdminController < ResourcesController; end
17
+ class ProductsController < ResourcesController; end
18
+ class ImagesController < ResourcesController; end
17
19
 
18
20
  module Backoffice
19
21
  class ProductsController < ResourcesController; end
@@ -264,6 +266,19 @@ class ResourcesTest < Test::Unit::TestCase
264
266
  end
265
267
  end
266
268
 
269
+ def test_array_as_collection_or_member_method_value
270
+ with_restful_routing :messages, :collection => { :search => [:get, :post] }, :member => { :toggle => [:get, :post] } do
271
+ assert_restful_routes_for :messages do |options|
272
+ [:get, :post].each do |method|
273
+ assert_recognizes(options.merge(:action => 'search'), :path => "/messages/search", :method => method)
274
+ end
275
+ [:get, :post].each do |method|
276
+ assert_recognizes(options.merge(:action => 'toggle', :id => '1'), :path => '/messages/1/toggle', :method => method)
277
+ end
278
+ end
279
+ end
280
+ end
281
+
267
282
  def test_with_new_action
268
283
  with_restful_routing :messages, :new => { :preview => :post } do
269
284
  preview_options = {:action => 'preview'}
@@ -366,6 +381,31 @@ class ResourcesTest < Test::Unit::TestCase
366
381
  end
367
382
  end
368
383
 
384
+ def test_shallow_nested_restful_routes
385
+ with_routing do |set|
386
+ set.draw do |map|
387
+ map.resources :threads, :shallow => true do |map|
388
+ map.resources :messages do |map|
389
+ map.resources :comments
390
+ end
391
+ end
392
+ end
393
+
394
+ assert_simply_restful_for :threads,
395
+ :shallow => true
396
+ assert_simply_restful_for :messages,
397
+ :name_prefix => 'thread_',
398
+ :path_prefix => 'threads/1/',
399
+ :shallow => true,
400
+ :options => { :thread_id => '1' }
401
+ assert_simply_restful_for :comments,
402
+ :name_prefix => 'message_',
403
+ :path_prefix => 'messages/2/',
404
+ :shallow => true,
405
+ :options => { :message_id => '2' }
406
+ end
407
+ end
408
+
369
409
  def test_restful_routes_dont_generate_duplicates
370
410
  with_restful_routing :messages do
371
411
  routes = ActionController::Routing::Routes.routes
@@ -416,6 +456,32 @@ class ResourcesTest < Test::Unit::TestCase
416
456
  end
417
457
  end
418
458
 
459
+ def test_resources_has_many_hash_should_become_nested_resources
460
+ with_routing do |set|
461
+ set.draw do |map|
462
+ map.resources :threads, :has_many => { :messages => [ :comments, { :authors => :threads } ] }
463
+ end
464
+
465
+ assert_simply_restful_for :threads
466
+ assert_simply_restful_for :messages, :name_prefix => "thread_", :path_prefix => 'threads/1/', :options => { :thread_id => '1' }
467
+ assert_simply_restful_for :comments, :name_prefix => "thread_message_", :path_prefix => 'threads/1/messages/1/', :options => { :thread_id => '1', :message_id => '1' }
468
+ assert_simply_restful_for :authors, :name_prefix => "thread_message_", :path_prefix => 'threads/1/messages/1/', :options => { :thread_id => '1', :message_id => '1' }
469
+ assert_simply_restful_for :threads, :name_prefix => "thread_message_author_", :path_prefix => 'threads/1/messages/1/authors/1/', :options => { :thread_id => '1', :message_id => '1', :author_id => '1' }
470
+ end
471
+ end
472
+
473
+ def test_shallow_resource_has_many_should_become_shallow_nested_resources
474
+ with_routing do |set|
475
+ set.draw do |map|
476
+ map.resources :messages, :has_many => [ :comments, :authors ], :shallow => true
477
+ end
478
+
479
+ assert_simply_restful_for :messages, :shallow => true
480
+ assert_simply_restful_for :comments, :name_prefix => "message_", :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
481
+ assert_simply_restful_for :authors, :name_prefix => "message_", :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
482
+ end
483
+ end
484
+
419
485
  def test_resource_has_one_should_become_nested_resources
420
486
  with_routing do |set|
421
487
  set.draw do |map|
@@ -427,6 +493,17 @@ class ResourcesTest < Test::Unit::TestCase
427
493
  end
428
494
  end
429
495
 
496
+ def test_shallow_resource_has_one_should_become_shallow_nested_resources
497
+ with_routing do |set|
498
+ set.draw do |map|
499
+ map.resources :messages, :has_one => :logo, :shallow => true
500
+ end
501
+
502
+ assert_simply_restful_for :messages, :shallow => true
503
+ assert_singleton_restful_for :logo, :name_prefix => 'message_', :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
504
+ end
505
+ end
506
+
430
507
  def test_singleton_resource_with_member_action
431
508
  [:put, :post].each do |method|
432
509
  with_singleton_resources :account, :member => { :reset => method } do
@@ -516,6 +593,26 @@ class ResourcesTest < Test::Unit::TestCase
516
593
  end
517
594
  end
518
595
 
596
+ def test_should_not_allow_invalid_head_method_for_member_routes
597
+ with_routing do |set|
598
+ set.draw do |map|
599
+ assert_raises(ArgumentError) do
600
+ map.resources :messages, :member => {:something => :head}
601
+ end
602
+ end
603
+ end
604
+ end
605
+
606
+ def test_should_not_allow_invalid_http_methods_for_member_routes
607
+ with_routing do |set|
608
+ set.draw do |map|
609
+ assert_raises(ArgumentError) do
610
+ map.resources :messages, :member => {:something => :invalid}
611
+ end
612
+ end
613
+ end
614
+ end
615
+
519
616
  def test_resource_action_separator
520
617
  with_routing do |set|
521
618
  set.draw do |map|
@@ -681,6 +778,225 @@ class ResourcesTest < Test::Unit::TestCase
681
778
  end
682
779
  end
683
780
 
781
+ def test_resource_has_only_show_action
782
+ with_routing do |set|
783
+ set.draw do |map|
784
+ map.resources :products, :only => :show
785
+ end
786
+
787
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, :show, [:index, :new, :create, :edit, :update, :destroy])
788
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, :show, [:index, :new, :create, :edit, :update, :destroy])
789
+ end
790
+ end
791
+
792
+ def test_singleton_resource_has_only_show_action
793
+ with_routing do |set|
794
+ set.draw do |map|
795
+ map.resource :account, :only => :show
796
+ end
797
+
798
+ assert_singleton_resource_allowed_routes('accounts', {}, :show, [:index, :new, :create, :edit, :update, :destroy])
799
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, :show, [:index, :new, :create, :edit, :update, :destroy])
800
+ end
801
+ end
802
+
803
+ def test_resource_does_not_have_destroy_action
804
+ with_routing do |set|
805
+ set.draw do |map|
806
+ map.resources :products, :except => :destroy
807
+ end
808
+
809
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, [:index, :new, :create, :show, :edit, :update], :destroy)
810
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, [:index, :new, :create, :show, :edit, :update], :destroy)
811
+ end
812
+ end
813
+
814
+ def test_singleton_resource_does_not_have_destroy_action
815
+ with_routing do |set|
816
+ set.draw do |map|
817
+ map.resource :account, :except => :destroy
818
+ end
819
+
820
+ assert_singleton_resource_allowed_routes('accounts', {}, [:new, :create, :show, :edit, :update], :destroy)
821
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, [:new, :create, :show, :edit, :update], :destroy)
822
+ end
823
+ end
824
+
825
+ def test_resource_has_only_create_action_and_named_route
826
+ with_routing do |set|
827
+ set.draw do |map|
828
+ map.resources :products, :only => :create
829
+ end
830
+
831
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, :create, [:index, :new, :show, :edit, :update, :destroy])
832
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, :create, [:index, :new, :show, :edit, :update, :destroy])
833
+
834
+ assert_not_nil set.named_routes[:products]
835
+ end
836
+ end
837
+
838
+ def test_resource_has_only_update_action_and_named_route
839
+ with_routing do |set|
840
+ set.draw do |map|
841
+ map.resources :products, :only => :update
842
+ end
843
+
844
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, :update, [:index, :new, :create, :show, :edit, :destroy])
845
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, :update, [:index, :new, :create, :show, :edit, :destroy])
846
+
847
+ assert_not_nil set.named_routes[:product]
848
+ end
849
+ end
850
+
851
+ def test_resource_has_only_destroy_action_and_named_route
852
+ with_routing do |set|
853
+ set.draw do |map|
854
+ map.resources :products, :only => :destroy
855
+ end
856
+
857
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, :destroy, [:index, :new, :create, :show, :edit, :update])
858
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, :destroy, [:index, :new, :create, :show, :edit, :update])
859
+
860
+ assert_not_nil set.named_routes[:product]
861
+ end
862
+ end
863
+
864
+ def test_singleton_resource_has_only_create_action_and_named_route
865
+ with_routing do |set|
866
+ set.draw do |map|
867
+ map.resource :account, :only => :create
868
+ end
869
+
870
+ assert_singleton_resource_allowed_routes('accounts', {}, :create, [:new, :show, :edit, :update, :destroy])
871
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, :create, [:new, :show, :edit, :update, :destroy])
872
+
873
+ assert_not_nil set.named_routes[:account]
874
+ end
875
+ end
876
+
877
+ def test_singleton_resource_has_only_update_action_and_named_route
878
+ with_routing do |set|
879
+ set.draw do |map|
880
+ map.resource :account, :only => :update
881
+ end
882
+
883
+ assert_singleton_resource_allowed_routes('accounts', {}, :update, [:new, :create, :show, :edit, :destroy])
884
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, :update, [:new, :create, :show, :edit, :destroy])
885
+
886
+ assert_not_nil set.named_routes[:account]
887
+ end
888
+ end
889
+
890
+ def test_singleton_resource_has_only_destroy_action_and_named_route
891
+ with_routing do |set|
892
+ set.draw do |map|
893
+ map.resource :account, :only => :destroy
894
+ end
895
+
896
+ assert_singleton_resource_allowed_routes('accounts', {}, :destroy, [:new, :create, :show, :edit, :update])
897
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, :destroy, [:new, :create, :show, :edit, :update])
898
+
899
+ assert_not_nil set.named_routes[:account]
900
+ end
901
+ end
902
+
903
+ def test_resource_has_only_collection_action
904
+ with_routing do |set|
905
+ set.draw do |map|
906
+ map.resources :products, :except => :all, :collection => { :sale => :get }
907
+ end
908
+
909
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, [], [:index, :new, :create, :show, :edit, :update, :destroy])
910
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, [], [:index, :new, :create, :show, :edit, :update, :destroy])
911
+
912
+ assert_recognizes({ :controller => 'products', :action => 'sale' }, :path => 'products/sale', :method => :get)
913
+ assert_recognizes({ :controller => 'products', :action => 'sale', :format => 'xml' }, :path => 'products/sale.xml', :method => :get)
914
+ end
915
+ end
916
+
917
+ def test_resource_has_only_member_action
918
+ with_routing do |set|
919
+ set.draw do |map|
920
+ map.resources :products, :except => :all, :member => { :preview => :get }
921
+ end
922
+
923
+ assert_resource_allowed_routes('products', {}, { :id => '1' }, [], [:index, :new, :create, :show, :edit, :update, :destroy])
924
+ assert_resource_allowed_routes('products', { :format => 'xml' }, { :id => '1' }, [], [:index, :new, :create, :show, :edit, :update, :destroy])
925
+
926
+ assert_recognizes({ :controller => 'products', :action => 'preview', :id => '1' }, :path => 'products/1/preview', :method => :get)
927
+ assert_recognizes({ :controller => 'products', :action => 'preview', :id => '1', :format => 'xml' }, :path => 'products/1/preview.xml', :method => :get)
928
+ end
929
+ end
930
+
931
+ def test_singleton_resource_has_only_member_action
932
+ with_routing do |set|
933
+ set.draw do |map|
934
+ map.resource :account, :except => :all, :member => { :signup => :get }
935
+ end
936
+
937
+ assert_singleton_resource_allowed_routes('accounts', {}, [], [:new, :create, :show, :edit, :update, :destroy])
938
+ assert_singleton_resource_allowed_routes('accounts', { :format => 'xml' }, [], [:new, :create, :show, :edit, :update, :destroy])
939
+
940
+ assert_recognizes({ :controller => 'accounts', :action => 'signup' }, :path => 'account/signup', :method => :get)
941
+ assert_recognizes({ :controller => 'accounts', :action => 'signup', :format => 'xml' }, :path => 'account/signup.xml', :method => :get)
942
+ end
943
+ end
944
+
945
+ def test_nested_resource_inherits_only_show_action
946
+ with_routing do |set|
947
+ set.draw do |map|
948
+ map.resources :products, :only => :show do |product|
949
+ product.resources :images
950
+ end
951
+ end
952
+
953
+ assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, :show, [:index, :new, :create, :edit, :update, :destroy], 'products/1/images')
954
+ assert_resource_allowed_routes('images', { :product_id => '1', :format => 'xml' }, { :id => '2' }, :show, [:index, :new, :create, :edit, :update, :destroy], 'products/1/images')
955
+ end
956
+ end
957
+
958
+ def test_nested_resource_has_only_show_and_member_action
959
+ with_routing do |set|
960
+ set.draw do |map|
961
+ map.resources :products, :only => [:index, :show] do |product|
962
+ product.resources :images, :member => { :thumbnail => :get }, :only => :show
963
+ end
964
+ end
965
+
966
+ assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, :show, [:index, :new, :create, :edit, :update, :destroy], 'products/1/images')
967
+ assert_resource_allowed_routes('images', { :product_id => '1', :format => 'xml' }, { :id => '2' }, :show, [:index, :new, :create, :edit, :update, :destroy], 'products/1/images')
968
+
969
+ assert_recognizes({ :controller => 'images', :action => 'thumbnail', :product_id => '1', :id => '2' }, :path => 'products/1/images/2/thumbnail', :method => :get)
970
+ assert_recognizes({ :controller => 'images', :action => 'thumbnail', :product_id => '1', :id => '2', :format => 'jpg' }, :path => 'products/1/images/2/thumbnail.jpg', :method => :get)
971
+ end
972
+ end
973
+
974
+ def test_nested_resource_ignores_only_option
975
+ with_routing do |set|
976
+ set.draw do |map|
977
+ map.resources :products, :only => :show do |product|
978
+ product.resources :images, :except => :destroy
979
+ end
980
+ end
981
+
982
+ assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, [:index, :new, :create, :show, :edit, :update], :destroy, 'products/1/images')
983
+ assert_resource_allowed_routes('images', { :product_id => '1', :format => 'xml' }, { :id => '2' }, [:index, :new, :create, :show, :edit, :update], :destroy, 'products/1/images')
984
+ end
985
+ end
986
+
987
+ def test_nested_resource_ignores_except_option
988
+ with_routing do |set|
989
+ set.draw do |map|
990
+ map.resources :products, :except => :show do |product|
991
+ product.resources :images, :only => :destroy
992
+ end
993
+ end
994
+
995
+ assert_resource_allowed_routes('images', { :product_id => '1' }, { :id => '2' }, :destroy, [:index, :new, :create, :show, :edit, :update], 'products/1/images')
996
+ assert_resource_allowed_routes('images', { :product_id => '1', :format => 'xml' }, { :id => '2' }, :destroy, [:index, :new, :create, :show, :edit, :update], 'products/1/images')
997
+ end
998
+ end
999
+
684
1000
  protected
685
1001
  def with_restful_routing(*args)
686
1002
  with_routing do |set|
@@ -711,6 +1027,13 @@ class ResourcesTest < Test::Unit::TestCase
711
1027
  options[:options] ||= {}
712
1028
  options[:options][:controller] = options[:controller] || controller_name.to_s
713
1029
 
1030
+ if options[:shallow]
1031
+ options[:shallow_options] ||= {}
1032
+ options[:shallow_options][:controller] = options[:options][:controller]
1033
+ else
1034
+ options[:shallow_options] = options[:options]
1035
+ end
1036
+
714
1037
  new_action = ActionController::Base.resources_path_names[:new] || "new"
715
1038
  edit_action = ActionController::Base.resources_path_names[:edit] || "edit"
716
1039
  if options[:path_names]
@@ -718,8 +1041,10 @@ class ResourcesTest < Test::Unit::TestCase
718
1041
  edit_action = options[:path_names][:edit] if options[:path_names][:edit]
719
1042
  end
720
1043
 
721
- collection_path = "/#{options[:path_prefix]}#{options[:as] || controller_name}"
722
- member_path = "#{collection_path}/1"
1044
+ path = "#{options[:as] || controller_name}"
1045
+ collection_path = "/#{options[:path_prefix]}#{path}"
1046
+ shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}"
1047
+ member_path = "#{shallow_path}/1"
723
1048
  new_path = "#{collection_path}/#{new_action}"
724
1049
  edit_member_path = "#{member_path}/#{edit_action}"
725
1050
  formatted_edit_member_path = "#{member_path}/#{edit_action}.xml"
@@ -727,10 +1052,13 @@ class ResourcesTest < Test::Unit::TestCase
727
1052
  with_options(options[:options]) do |controller|
728
1053
  controller.assert_routing collection_path, :action => 'index'
729
1054
  controller.assert_routing new_path, :action => 'new'
730
- controller.assert_routing member_path, :action => 'show', :id => '1'
731
- controller.assert_routing edit_member_path, :action => 'edit', :id => '1'
732
1055
  controller.assert_routing "#{collection_path}.xml", :action => 'index', :format => 'xml'
733
1056
  controller.assert_routing "#{new_path}.xml", :action => 'new', :format => 'xml'
1057
+ end
1058
+
1059
+ with_options(options[:shallow_options]) do |controller|
1060
+ controller.assert_routing member_path, :action => 'show', :id => '1'
1061
+ controller.assert_routing edit_member_path, :action => 'edit', :id => '1'
734
1062
  controller.assert_routing "#{member_path}.xml", :action => 'show', :id => '1', :format => 'xml'
735
1063
  controller.assert_routing formatted_edit_member_path, :action => 'edit', :id => '1', :format => 'xml'
736
1064
  end
@@ -738,18 +1066,18 @@ class ResourcesTest < Test::Unit::TestCase
738
1066
  assert_recognizes(options[:options].merge(:action => 'index'), :path => collection_path, :method => :get)
739
1067
  assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get)
740
1068
  assert_recognizes(options[:options].merge(:action => 'create'), :path => collection_path, :method => :post)
741
- assert_recognizes(options[:options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get)
742
- assert_recognizes(options[:options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get)
743
- assert_recognizes(options[:options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put)
744
- assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete)
745
-
746
- assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get)
747
- assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get)
748
- assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post)
749
- assert_recognizes(options[:options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get)
750
- assert_recognizes(options[:options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get)
751
- assert_recognizes(options[:options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put)
752
- assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete)
1069
+ assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get)
1070
+ assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get)
1071
+ assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put)
1072
+ assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete)
1073
+
1074
+ assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get)
1075
+ assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get)
1076
+ assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post)
1077
+ assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get)
1078
+ assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get)
1079
+ assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put)
1080
+ assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete)
753
1081
 
754
1082
  yield options[:options] if block_given?
755
1083
  end
@@ -765,14 +1093,24 @@ class ResourcesTest < Test::Unit::TestCase
765
1093
  options[:options] ||= {}
766
1094
  options[:options][:controller] = options[:controller] || controller_name.to_s
767
1095
 
1096
+ if options[:shallow]
1097
+ options[:shallow_options] ||= {}
1098
+ options[:shallow_options][:controller] = options[:options][:controller]
1099
+ else
1100
+ options[:shallow_options] = options[:options]
1101
+ end
1102
+
768
1103
  @controller = "#{options[:options][:controller].camelize}Controller".constantize.new
769
1104
  @request = ActionController::TestRequest.new
770
1105
  @response = ActionController::TestResponse.new
771
1106
  get :index, options[:options]
772
1107
  options[:options].delete :action
773
1108
 
774
- full_prefix = "/#{options[:path_prefix]}#{options[:as] || controller_name}"
1109
+ path = "#{options[:as] || controller_name}"
1110
+ shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}"
1111
+ full_path = "/#{options[:path_prefix]}#{path}"
775
1112
  name_prefix = options[:name_prefix]
1113
+ shallow_prefix = "#{options[:name_prefix] unless options[:shallow]}"
776
1114
 
777
1115
  new_action = "new"
778
1116
  edit_action = "edit"
@@ -781,15 +1119,15 @@ class ResourcesTest < Test::Unit::TestCase
781
1119
  edit_action = options[:path_names][:edit] || "edit"
782
1120
  end
783
1121
 
784
- assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options]
785
- assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml')
786
- assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
787
- assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
1122
+ assert_named_route "#{full_path}", "#{name_prefix}#{controller_name}_path", options[:options]
1123
+ assert_named_route "#{full_path}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge(:format => 'xml')
1124
+ assert_named_route "#{shallow_path}/1", "#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1')
1125
+ assert_named_route "#{shallow_path}/1.xml", "formatted_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml')
788
1126
 
789
- assert_named_route "#{full_prefix}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", options[:options]
790
- assert_named_route "#{full_prefix}/#{new_action}.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml')
791
- assert_named_route "#{full_prefix}/1/#{edit_action}", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
792
- assert_named_route "#{full_prefix}/1/#{edit_action}.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
1127
+ assert_named_route "#{full_path}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", options[:options]
1128
+ assert_named_route "#{full_path}/#{new_action}.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge(:format => 'xml')
1129
+ assert_named_route "#{shallow_path}/1/#{edit_action}", "edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1')
1130
+ assert_named_route "#{shallow_path}/1/#{edit_action}.xml", "formatted_edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml')
793
1131
 
794
1132
  yield options[:options] if block_given?
795
1133
  end
@@ -862,6 +1200,51 @@ class ResourcesTest < Test::Unit::TestCase
862
1200
  end
863
1201
  end
864
1202
 
1203
+ def assert_resource_allowed_routes(controller, options, shallow_options, allowed, not_allowed, path = controller)
1204
+ shallow_path = "#{path}/#{shallow_options[:id]}"
1205
+ format = options[:format] && ".#{options[:format]}"
1206
+ options.merge!(:controller => controller)
1207
+ shallow_options.merge!(options)
1208
+
1209
+ assert_whether_allowed(allowed, not_allowed, options, 'index', "#{path}#{format}", :get)
1210
+ assert_whether_allowed(allowed, not_allowed, options, 'new', "#{path}/new#{format}", :get)
1211
+ assert_whether_allowed(allowed, not_allowed, options, 'create', "#{path}#{format}", :post)
1212
+ assert_whether_allowed(allowed, not_allowed, shallow_options, 'show', "#{shallow_path}#{format}", :get)
1213
+ assert_whether_allowed(allowed, not_allowed, shallow_options, 'edit', "#{shallow_path}/edit#{format}", :get)
1214
+ assert_whether_allowed(allowed, not_allowed, shallow_options, 'update', "#{shallow_path}#{format}", :put)
1215
+ assert_whether_allowed(allowed, not_allowed, shallow_options, 'destroy', "#{shallow_path}#{format}", :delete)
1216
+ end
1217
+
1218
+ def assert_singleton_resource_allowed_routes(controller, options, allowed, not_allowed, path = controller.singularize)
1219
+ format = options[:format] && ".#{options[:format]}"
1220
+ options.merge!(:controller => controller)
1221
+
1222
+ assert_whether_allowed(allowed, not_allowed, options, 'new', "#{path}/new#{format}", :get)
1223
+ assert_whether_allowed(allowed, not_allowed, options, 'create', "#{path}#{format}", :post)
1224
+ assert_whether_allowed(allowed, not_allowed, options, 'show', "#{path}#{format}", :get)
1225
+ assert_whether_allowed(allowed, not_allowed, options, 'edit', "#{path}/edit#{format}", :get)
1226
+ assert_whether_allowed(allowed, not_allowed, options, 'update', "#{path}#{format}", :put)
1227
+ assert_whether_allowed(allowed, not_allowed, options, 'destroy', "#{path}#{format}", :delete)
1228
+ end
1229
+
1230
+ def assert_whether_allowed(allowed, not_allowed, options, action, path, method)
1231
+ action = action.to_sym
1232
+ options = options.merge(:action => action.to_s)
1233
+ path_options = { :path => path, :method => method }
1234
+
1235
+ if Array(allowed).include?(action)
1236
+ assert_recognizes options, path_options
1237
+ elsif Array(not_allowed).include?(action)
1238
+ assert_not_recognizes options, path_options
1239
+ end
1240
+ end
1241
+
1242
+ def assert_not_recognizes(expected_options, path)
1243
+ assert_raise ActionController::RoutingError, ActionController::MethodNotAllowed, Test::Unit::AssertionFailedError do
1244
+ assert_recognizes(expected_options, path)
1245
+ end
1246
+ end
1247
+
865
1248
  def distinct_routes? (r1, r2)
866
1249
  if r1.conditions == r2.conditions and r1.requirements == r2.requirements then
867
1250
  if r1.segments.collect(&:to_s) == r2.segments.collect(&:to_s) then