Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #11491: render_partial_collection_with_multiple_element_types.patch

File render_partial_collection_with_multiple_element_types.patch, 6.1 kB (added by zdennis, 5 months ago)

Patch to allow render partial => collection work with different types of records

  • test/controller/new_render_test.rb

    old new  
    162162  def partial_collection_shorthand_with_locals 
    163163    render :partial => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" } 
    164164  end 
     165   
     166  def partial_collection_shorthand_with_different_types_of_records 
     167    render :partial => [  
     168        BadCustomer.new("mark"),  
     169        GoodCustomer.new("craig"),  
     170        BadCustomer.new("john"), 
     171        GoodCustomer.new("zach"),  
     172        GoodCustomer.new("brandon"),  
     173        BadCustomer.new("dan") ],  
     174      :locals => { :greeting => "Bonjour" } 
     175  end 
    165176 
     177  def partial_collection_shorthand_with_different_types_of_records_with_counter 
     178    partial_collection_shorthand_with_different_types_of_records 
     179  end 
     180 
    166181  def empty_partial_collection 
    167182    render :partial => "customer", :collection => [] 
    168183  end 
     
    740755    get :partial_collection_shorthand_with_locals 
    741756    assert_equal "Bonjour: davidBonjour: mary", @response.body 
    742757  end 
    743  
     758   
     759  def test_partial_collection_shorthand_with_different_types_of_records 
     760    get :partial_collection_shorthand_with_different_types_of_records     
     761    assert_equal "Bonjour bad customer: mark1Bonjour good customer: craig2Bonjour bad customer: john3Bonjour good customer: zach4Bonjour good customer: brandon5Bonjour bad customer: dan6", @response.body 
     762  end 
     763   
    744764  def test_empty_partial_collection 
    745765    get :empty_partial_collection 
    746766    assert_equal " ", @response.body 
  • test/controller/fake_models.rb

    old new  
    33    id.to_s 
    44  end 
    55end 
     6 
     7class BadCustomer < Customer 
     8end 
     9 
     10class GoodCustomer < Customer 
     11end 
     12   
  • test/fixtures/good_customers/_good_customer.html.erb

    old new  
  • test/fixtures/bad_customers/_bad_customer.html.erb

    old new  
  • lib/action_view/partials.rb

    old new  
    113113          render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path)) 
    114114        when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Associations::HasManyThroughAssociation 
    115115          if partial_path.any? 
    116             path       = ActionController::RecordIdentifier.partial_path(partial_path.first) 
    117116            collection = partial_path 
    118             render_partial_collection(path, collection, nil, local_assigns) 
     117            render_partial_collection(nil, collection, nil, local_assigns) 
    119118          else 
    120119            "" 
    121120          end 
     
    126125 
    127126      def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}) #:nodoc: 
    128127        return " " if collection.empty? 
    129          
     128 
    130129        local_assigns = local_assigns ? local_assigns.clone : {} 
     130        spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' 
     131                 
     132        if partial_path.nil? 
     133          render_partial_collection_with_unknown_partial_path(collection, local_assigns, spacer) 
     134        else 
     135          render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, spacer) 
     136        end.join(spacer) 
     137      end 
     138 
     139      def render_partial_collection_with_known_partial_path(collection, partial_path, local_assigns, spacer) 
    131140        template = ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) 
    132          
    133         spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : '' 
    134          
    135141        collection.map do |element| 
    136142          template.render_member(element) 
    137         end.join(spacer) 
     143        end 
    138144      end 
     145       
     146      def render_partial_collection_with_unknown_partial_path(collection, local_assigns, spacer) 
     147        templates = Hash.new 
     148        i = 0 
     149        collection.map do |element| 
     150          partial_path = ActionController::RecordIdentifier.partial_path(element)  
     151          template = templates[partial_path] ||= ActionView::PartialTemplate.new(self, partial_path, nil, local_assigns) 
     152          template.counter = i 
     153          i += 1 
     154          template.render_member(element) 
     155        end 
     156      end 
    139157  end 
    140158end 
  • lib/action_view/partial_template.rb

    old new  
    77      @path, @variable_name = extract_partial_name_and_path(view, partial_path) 
    88      super(view, @path, true, locals) 
    99      add_object_to_local_assigns!(object) 
    10        
     10 
    1111      # This is needed here in order to compile template with knowledge of 'counter' 
    1212      initialize_counter 
    1313       
     
    2424    def render_member(object) 
    2525      @locals[@counter_name] += 1 
    2626      @locals[:object] = @locals[@variable_name] = object 
    27       render 
     27      returning render do 
     28        @locals.delete(@variable_name) 
     29        @locals.delete(:object) 
     30      end 
    2831    end 
    2932     
     33    def counter=(num) 
     34      @locals[@counter_name] = num 
     35    end 
     36     
    3037    private 
    31      
     38 
    3239    def add_object_to_local_assigns!(object) 
    3340      @locals[:object] ||= 
    3441        @locals[@variable_name] ||=