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

Changeset 4379

Show
Ignore:
Timestamp:
05/29/06 03:48:17 (2 years ago)
Author:
rick
Message:

Fix the has_and_belongs_to_many #create doesn't populate the join for new records. Closes #3692 [josh@hasmanythrough.com]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r4372 r4379  
    11*SVN* 
     2 
     3* Fix the has_and_belongs_to_many #create doesn't populate the join for new records.  Closes #3692 [josh@hasmanythrough.com] 
    24 
    35* Provide Association Extensions access to the instance that the association is being accessed from.   
  • trunk/activerecord/lib/active_record/associations.rb

    r4372 r4379  
    764764      # * <tt>collection.find(id)</tt> - finds an associated object responding to the +id+ and that 
    765765      #   meets the condition that it has to be associated with this object. 
     766      # * <tt>collection.build(attributes = {})</tt> - returns a new object of the collection type that has been instantiated 
     767      #   with +attributes+ and linked to this object through the join table but has not yet been saved. 
     768      # * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated 
     769      #   with +attributes+ and linked to this object through the join table and that has already been saved (if it passed the validation). 
    766770      # 
    767771      # Example: An Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add: 
     
    776780      # * <tt>Developer#projects.size</tt> 
    777781      # * <tt>Developer#projects.find(id)</tt> 
     782      # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>) 
     783      # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>) 
    778784      # The declaration may include an options hash to specialize the behavior of the association. 
    779785      #  
  • trunk/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb

    r4325 r4379  
    1212        @target << record 
    1313        record 
     14      end 
     15 
     16      def create(attributes = {}) 
     17        # Can't use Base.create since the foreign key may be a protected attribute. 
     18        if attributes.is_a?(Array) 
     19          attributes.collect { |attr| create(attr) } 
     20        else 
     21          record = build(attributes) 
     22          insert_record(record) unless @owner.new_record? 
     23          record 
     24        end 
    1425      end 
    1526 
  • trunk/activerecord/test/associations_test.rb

    r4372 r4379  
    13551355    assert !proj.new_record? 
    13561356    assert_equal devel.projects.last, proj 
     1357    assert_equal Developer.find(1).projects.last, proj  # prove join table is updated 
     1358  end 
     1359   
     1360  def test_build_by_new_record 
     1361    devel = Developer.new(:name => "Marcel", :salary => 75000) 
     1362    proj1 = devel.projects.build(:name => "Make bed") 
     1363    proj2 = devel.projects.build(:name => "Lie in it") 
     1364    assert_equal devel.projects.last, proj2 
     1365    assert proj2.new_record? 
     1366    devel.save 
     1367    assert !devel.new_record? 
     1368    assert !proj2.new_record? 
     1369    assert_equal devel.projects.last, proj2 
     1370    assert_equal Developer.find_by_name("Marcel").projects.last, proj2  # prove join table is updated 
    13571371  end 
    13581372   
     
    13621376    assert_equal devel.projects.last, proj 
    13631377    assert !proj.new_record? 
     1378    assert_equal Developer.find(1).projects.last, proj  # prove join table is updated 
     1379  end 
     1380   
     1381  def test_create_by_new_record 
     1382    devel = Developer.new(:name => "Marcel", :salary => 75000) 
     1383    proj1 = devel.projects.create(:name => "Make bed") 
     1384    proj2 = devel.projects.create(:name => "Lie in it") 
     1385    assert_equal devel.projects.last, proj2 
     1386    assert proj2.new_record? 
     1387    devel.save 
     1388    assert !devel.new_record? 
     1389    assert !proj2.new_record? 
     1390    assert_equal devel.projects.last, proj2 
     1391    assert_equal Developer.find_by_name("Marcel").projects.last, proj2  # prove join table is updated 
    13641392  end 
    13651393