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

Ticket #3259 (closed defect: untested)

Opened 3 years ago

Last modified 1 year ago

Many-to-many associations require "pre-save"

Reported by: chris@aquaphile.org Assigned to: David
Priority: normal Milestone: 1.2.4
Component: ActiveRecord Version: 1.1.1
Severity: normal Keywords: habtm
Cc:

Description

If you have a many-to-many association, with the corresponding join table, you must save the model receiving the collection of attribute models prior to using the << or push_with_attributes methods. If you don't do the "pre-save" the records in the joing table will not be created.

For instance,

class Driver < ActiveRecord::Base
  has_and_belongs_to_many :policies
end

class Policy < ActiveRecord::Base
  has_and_belongs_to_many :drivers
end

drivers
------
id  (primary key)
name
dl_num

policies
------
id  (primary key)
started_on
coverage

drivers_policies
---------
driver_id  (primary key, foreign key)
policy_id  (primary key, foreign key)
is_primary_driver

To create the problem:

1) I had an unsaved (no database record, yet) Policy add an unsaved Driver.

@policy.drivers.push_with_attributes(@driver, :is_primary_driver => TRUE)

or

@policy.drivers << @driver

2) Then I saved the Policy

@policy.save

3) Then I looked in the drivers_policies table for a record.

I found that if I call @policy.save prior to adding a collection (either << or push_with_attributes), then the relationships were properly recognized and persisted by a later @policy.save.

I am using Rails 14.3 and PostGreSQL.

Change History

12/16/05 23:52:44 changed by chris@aquaphile.org

  • version changed from 0.14.3 to 1.0.0.

I upgraded to 1.0 and the bug still exists

12/16/05 23:54:16 changed by chris@aquaphile.org

  • summary changed from Many-to-many associations require saving records prior to to Many-to-many associations require "pre-save".

12/17/05 01:53:03 changed by jcabrer@hra.com

I have a table with three (3) many-to-many associations (implemented as multi-checkboxes) in my NEW and EDIT forms. Intrestingly, the first of the three associations takes when entered from NEW (without pre-save), the others do not. Changing the order in which they appear in my controller does not affect this. That is, the same many-to-many is saved (bodyparts).

On subsequent edit/updates, everything else works fine.

  def create
    @incident = Incident.new(params[:incident])
    @incident.bodyparts = Bodypart.find(@params[:bodypart_ids]) if @params[:bodypart_ids]
    @incident.vehicle_damages = VehicleDamage.find(@params[:vehicle_damage_ids]) if @params[:vehicle_damage_ids]
    @incident.weather_conditions = WeatherCondition.find(@params[:weather_condition_ids]) if @params[:weather_condition_ids]
    if @incident.save
      flash[:notice] = 'Incident was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end
  def update
    @incident = Incident.find(params[:id])
    @incident.bodyparts = Bodypart.find(@params[:bodypart_ids]) if @params[:bodypart_ids]
    @incident.vehicle_damages = VehicleDamage.find(@params[:vehicle_damage_ids]) if @params[:vehicle_damage_ids]
    @incident.weather_conditions = WeatherCondition.find(@params[:weather_condition_ids]) if @params[:weather_condition_ids]
    if @incident.update_attributes(params[:incident])
      flash[:notice] = 'Incident was successfully updated.'
      redirect_to :action => 'show', :id => @incident
    else
      render :action => 'edit'
    end
  end

12/28/05 23:06:43 changed by Bill Burcham

I had the same problem -- habtm was requiring "pre-save". I applied the patch associated with ticket 3244 to my ActiveRecord 1.13.1 and my habtm no longer requires a "pre-save". Note: had to apply some of the patch by hand since I wasn't at 1.14 yet.

04/24/06 16:27:37 changed by chris@aquaphile.org

  • version changed from 1.0.0 to 1.1.1.

I have updated to Rails 1.1.2 and ActiveRecord 1.14.2 yet the "pre-save" is still required.

05/24/07 07:55:10 changed by danger

Can anyone verify that this bug still exists?

06/20/07 02:31:18 changed by bwyrosdick

If you do a many-to-many using has many through then it will not let you add the record it tells you ...

ActiveRecord::HasManyThroughCantAssociateNewRecords: Cannot associate new records through 'User#registrations' on '#'. Both records must have an id in order to create the has_many :through record associating them.

but using a has_and_belongs_to_many it still doesn't add the record or give you any warning

06/20/07 02:32:26 changed by bwyrosdick

That is as of revision 7064

06/23/07 02:04:49 changed by bitsweat

  • keywords set to habtm.
  • status changed from new to closed.
  • resolution set to untested.
  • milestone set to 1.2.4.

This should be a simple patch -- why is there no forward progress here?

Please write a unit test and patch. Raise an appropriate exception when pushing records onto a habtm whose owner is unsaved.