Ticket #6432: polymorphic_nested_routes.patch
| File polymorphic_nested_routes.patch, 10.7 kB (added by gravelpup, 3 years ago) |
|---|
-
actionpack/test/template/url_helper_test.rb
old new 375 375 end 376 376 end 377 377 378 class Session 379 attr_accessor :id, :workshop_id, :new_record 380 381 def initialize(id, new_record) 382 @id, @new_record = id, new_record 383 end 384 385 # def save; @id = 1; @post_id = 1 end 386 387 def new_record? 388 @new_record 389 end 390 391 def to_s 392 id.to_s 393 end 394 end 395 378 396 class PolymorphicControllerTest < Test::Unit::TestCase 379 397 class WorkshopsController < ActionController::Base 380 398 self.view_paths = ["#{File.dirname(__FILE__)}/../fixtures/"] … … 394 412 def rescue_action(e) raise e end 395 413 end 396 414 415 class SessionsController < ActionController::Base 416 self.view_paths = ["#{File.dirname(__FILE__)}/../fixtures/"] 417 418 def self.controller_path; 'sessions' end 419 420 def index 421 @workshop = Workshop.new(params[:workshop_id], false) 422 @session = Session.new(1, true) 423 render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" 424 end 425 426 def show 427 @workshop = Workshop.new(params[:workshop_id], false) 428 @session = Session.new(params[:id], false) 429 render :inline => "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" 430 end 431 432 def rescue_action(e) raise e end 433 end 434 397 435 include ActionView::Helpers::UrlHelper 398 436 399 437 def setup 400 438 @request = ActionController::TestRequest.new 401 439 @response = ActionController::TestResponse.new 402 @controller = WorkshopsController.new403 440 end 404 441 405 442 def test_new_resource 443 @controller = WorkshopsController.new 444 406 445 with_restful_routing do 407 446 get :index 408 447 assert_equal "/workshops\n<a href=\"/workshops\">Workshop</a>", @response.body … … 410 449 end 411 450 412 451 def test_existing_resource 452 @controller = WorkshopsController.new 453 413 454 with_restful_routing do 414 455 get :show, :id => 1 415 456 assert_equal "/workshops/1\n<a href=\"/workshops/1\">Workshop</a>", @response.body 416 457 end 417 458 end 418 459 460 def test_new_nested_resource 461 @controller = SessionsController.new 462 463 with_restful_routing do 464 get :index, :workshop_id => 1 465 assert_equal "/workshops/1/sessions\n<a href=\"/workshops/1/sessions\">Session</a>", @response.body 466 end 467 end 468 469 def test_existing_nested_resource 470 @controller = SessionsController.new 471 472 with_restful_routing do 473 get :show, :workshop_id => 1, :id => 1 474 assert_equal "/workshops/1/sessions/1\n<a href=\"/workshops/1/sessions/1\">Session</a>", @response.body 475 end 476 end 477 419 478 protected 420 479 def with_restful_routing 421 480 with_routing do |set| 422 481 set.draw do |map| 423 map.resources :workshops 482 map.resources :workshops do |w| 483 w.resources :sessions 484 end 424 485 end 425 486 yield 426 487 end -
actionpack/test/template/form_helper_test.rb
old new 15 15 @new_record 16 16 end 17 17 end 18 19 class Comment 20 attr_reader :id 21 attr_reader :post_id 22 def save; @id = 1; @post_id = 1 end 23 def new_record?; @id.nil? end 24 def name 25 @id.nil? ? 'new comment' : "comment ##{@id}" 26 end 27 end 18 28 end 19 29 30 class Comment::Nested < Comment; end 31 32 class Test::Unit::TestCase 33 protected 34 def comments_path(post) 35 "/posts/#{post.id}/comments" 36 end 37 38 def comment_path(post, comment) 39 "/posts/#{post.id}/comments/#{comment.id}" 40 end 41 end 42 20 43 class FormHelperTest < Test::Unit::TestCase 21 44 include ActionView::Helpers::FormHelper 22 45 include ActionView::Helpers::FormTagHelper … … 28 51 29 52 def setup 30 53 @post = Post.new 54 @comment = Comment.new 31 55 def @post.errors() 32 56 Class.new{ 33 57 def on(field); "can't be empty" if field == "author_name"; end … … 579 603 assert_equal expected, _erbout 580 604 end 581 605 606 def test_form_for_with_existing_object_in_list 607 @post.new_record = false 608 @comment.save 609 _erbout = '' 610 form_for([ @post, @comment ]) {} 611 612 expected = "<form action=\"#{comment_path(@post, @comment)}\" class=\"edit_comment\" id=\"edit_comment_1\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>" 613 assert_dom_equal expected, _erbout 614 end 615 616 def test_form_for_with_new_object_in_list 617 @post.new_record = false 618 _erbout = '' 619 form_for([ @post, @comment ]) {} 620 621 expected = "<form action=\"#{comments_path(@post)}\" class=\"new_comment\" id=\"new_comment\" method=\"post\"></form>" 622 assert_dom_equal expected, _erbout 623 end 624 582 625 def test_form_for_with_existing_object_and_custom_url 583 626 _erbout = '' 584 627 … … 600 643 601 644 602 645 protected 603 def polymorphic_path(record) 604 if record.new_record? 605 "/posts" 646 def polymorphic_path(object, *nested_objects) 647 if nested_objects.empty? 648 if object.new_record? 649 "/posts" 650 else 651 "/posts/#{object.id}" 652 end 606 653 else 607 "/posts/#{record.id}" 654 if object.new_record? 655 "/posts/123/comments" 656 else 657 "/posts/123/comments/#{object.id}" 658 end 608 659 end 609 660 end 610 661 end -
actionpack/lib/action_controller/record_identifier.rb
old new 25 25 # end 26 26 # end 27 27 # 28 # As the example above shows, you can stop caring to a large exten dwhat the actual id of the post is. You just know28 # As the example above shows, you can stop caring to a large extent what the actual id of the post is. You just know 29 29 # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming 30 30 # convention and allows you to write less code if you follow it. 31 31 module RecordIdentifier -
actionpack/lib/action_controller/polymorphic_routes.rb
old new 1 1 module ActionController 2 2 module PolymorphicRoutes 3 def polymorphic_url(record_or_hash , options = {})4 record = extract_record(record_or_hash )3 def polymorphic_url(record_or_hash_or_array, options = {}) 4 record = extract_record(record_or_hash_or_array) 5 5 6 6 case 7 7 when options[:action] == "new" 8 8 send( 9 action_prefix(options) + RecordIdentifier.singular_class_name(record) + routing_type(options)9 build_named_route_call(record_or_hash_or_array, :singular, options) 10 10 ) 11 11 12 12 when record.respond_to?(:new_record?) && record.new_record? 13 13 send( 14 action_prefix(options) + RecordIdentifier.plural_class_name(record) + routing_type(options)14 build_named_route_call(record_or_hash_or_array, :plural, options) 15 15 ) 16 16 17 17 else 18 18 send( 19 action_prefix(options) + RecordIdentifier.singular_class_name(record) + routing_type(options), record_or_hash19 build_named_route_call(record_or_hash_or_array, :singular, options), record_or_hash_or_array 20 20 ) 21 21 end 22 22 end 23 23 24 def polymorphic_path(record_or_hash )25 polymorphic_url(record_or_hash , :routing_type => :path)24 def polymorphic_path(record_or_hash_or_array) 25 polymorphic_url(record_or_hash_or_array, :routing_type => :path) 26 26 end 27 27 28 28 %w( edit new formatted ).each do |action| … … 44 44 end 45 45 46 46 def routing_type(options) 47 " _#{options[:routing_type] || "url"}"47 "#{options[:routing_type] || "url"}" 48 48 end 49 49 50 def extract_record(record_or_hash) 51 record_or_hash.is_a?(Hash) ? record_or_hash[:id] : record_or_hash 50 def build_named_route_call(records, singular_or_plural, options = {}) 51 records = Array.new([extract_record(records)]) unless records.is_a?(Array) 52 base_segment = "#{RecordIdentifier.send("#{singular_or_plural.to_s}_class_name", records.pop)}_" 53 54 method_root = records.reverse.inject(base_segment) do |string, name| 55 segment = "#{RecordIdentifier.send("singular_class_name", name)}_" 56 segment << string 57 end 58 59 action_prefix(options) + method_root + routing_type(options) 52 60 end 61 62 def extract_record(record_or_hash_or_array) 63 case record_or_hash_or_array 64 when Array: record_or_hash_or_array.last 65 when Hash: record_or_hash_or_array[:id] 66 else record_or_hash_or_array 67 end 68 end 53 69 end 54 70 end -
actionpack/lib/action_view/helpers/form_helper.rb
old new 163 163 case record_or_name 164 164 when String, Symbol 165 165 object_name = record_or_name 166 when Array 167 object = record_or_name.last 168 object_name = ActionController::RecordIdentifier.singular_class_name(object) 169 apply_form_for_options!(object, options, *record_or_name) 170 args.unshift object 166 171 else 167 object = record_or_name168 object_name = ActionController::RecordIdentifier.singular_class_name( record_or_name)172 object = record_or_name 173 object_name = ActionController::RecordIdentifier.singular_class_name(object) 169 174 apply_form_for_options!(object, options) 170 175 args.unshift object 171 176 end … … 175 180 concat('</form>', proc.binding) 176 181 end 177 182 178 def apply_form_for_options!(object, options ) #:nodoc:183 def apply_form_for_options!(object, options, *nested_objects) #:nodoc: 179 184 html_options = if object.respond_to?(:new_record?) && object.new_record? 180 185 { :class => dom_class(object, :new), :id => dom_id(object), :method => :post } 181 186 else … … 184 189 185 190 options[:html] ||= {} 186 191 options[:html].reverse_merge!(html_options) 187 188 options[:url] ||= polymorphic_path(object) 192 options[:url] ||= polymorphic_path(object, *nested_objects) 189 193 end 190 194 191 195 # Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes