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

Ticket #7352: activeresource_clone_patch_updated_for_r9089.diff

File activeresource_clone_patch_updated_for_r9089.diff, 3.6 kB (added by thechrisoshow, 3 months ago)

Updated for r9089 (includes tests and docs)

  • activeresource/test/base_test.rb

    old new  
    508508    end     
    509509    assert_raises(ActiveResource::ResourceConflict) { Person.create(:name => 'Rick') } 
    510510  end 
     511   
     512  def test_clone 
     513   matz = Person.find(1)  
     514   matz_c = matz.clone  
     515   assert matz_c.new?  
     516   matz.attributes.each do |k, v|  
     517     assert_equal v, matz_c.send(k) if k != Person.primary_key  
     518   end  
     519 end  
     520  
     521 def test_nested_clone 
     522   addy = StreetAddress.find(1, :params => {:person_id => 1})  
     523   addy_c = addy.clone  
     524   assert addy_c.new?  
     525   addy.attributes.each do |k, v|  
     526     assert_equal v, addy_c.send(k) if k != StreetAddress.primary_key  
     527   end  
     528   assert_equal addy.prefix_options, addy_c.prefix_options  
     529 end  
     530  
     531 def test_complex_clone 
     532   matz = Person.find(1)  
     533   matz.address = StreetAddress.find(1, :params => {:person_id => matz.id})  
     534   matz.non_ar_hash = {:not => "an ARes instance"}  
     535   matz.non_ar_arr = ["not", "ARes"]  
     536   matz_c = matz.clone  
     537   assert matz_c.new?  
     538   assert_raises(NoMethodError) {matz_c.address}  
     539   assert_equal matz.non_ar_hash, matz_c.non_ar_hash  
     540   assert_equal matz.non_ar_arr, matz_c.non_ar_arr  
     541     
     542   # Test that actual copy, not just reference copy  
     543   matz.non_ar_hash[:not] = "changed"  
     544   assert_not_equal matz.non_ar_hash, matz_c.non_ar_hash  
     545 end 
    511546 
    512547  def test_update 
    513548    matz = Person.find(:first) 
  • activeresource/lib/active_resource/base.rb

    old new  
    605605      @prefix_options = {} 
    606606      load(attributes) 
    607607    end 
     608     
     609    # Returns a clone of the resource that hasn't been assigned an id yet and  
     610    # is treated as a new resource.  
     611    #  
     612    #  ryan = Person.find(1)  
     613    #  not_ryan = ryan.clone  
     614    #  not_ryan.new?  # => true  
     615    #  
     616    # Any active resource member attributes will NOT be cloned, though all other  
     617    # attributes are.  This is to prevent the conflict between any prefix_options  
     618    # that refer to the original parent resource and the newly cloned parent  
     619    # resource that does not exist.  
     620    #  
     621    #  ryan = Person.find(1)  
     622    #  ryan.address = StreetAddress.find(1, :person_id => ryan.id)  
     623    #  ryan.hash = {:not => "an ARes instance"}  
     624    #  
     625    #  not_ryan = ryan.clone  
     626    #  not_ryan.new?            # => true  
     627    #  not_ryan.address         # => NoMethodError  
     628    #  not_ryan.hash            # => {:not => "an ARes instance"}  
     629    #  
     630    def clone         
     631      # Clone all attributes except the pk and any nested ARes  
     632      attrs = self.attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.inject({}) do |attrs, (k, v)|  
     633        attrs[k] = v.clone  
     634        attrs  
     635      end     
     636      # Form the new resource - bypass initialize of resource with 'new' as that will call 'load' which  
     637      # attempts to convert hashes into member objects and arrays into collections of objects.  We want  
     638      # the raw objects to be cloned so we bypass load by directly setting the attributes hash.  
     639      resource = self.class.new({}) 
     640      resource.prefix_options = self.prefix_options 
     641      resource.send :instance_variable_set, '@attributes', attrs  
     642      resource  
     643    end  
    608644 
     645 
    609646    # A method to determine if the resource a new object (i.e., it has not been POSTed to the remote service yet). 
    610647    # 
    611648    # ==== Examples