Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Saving object with nested attributes results in duplicates

#3783

I've looked for this problem in other tickets but nobody seems to have run across it.

Problem/Issue Description

I use forms and nested attributes to create an Album. An album has many tracks, a track has many artists. When the Album gets saved (not on instantiation), each artist gets attached to its corresponding track twice. Here's my code, I've included relevant fields:

class Album < ActiveRecord::Base
  has_many :tracks, :dependent => :destroy

  accepts_nested_attributes_for :tracks
end

class Track < ActiveRecord::Base
  belongs_to :album
  has_and_belongs_to_many :artists
  has_and_belongs_to_many :composers

  accepts_nested_attributes_for :artists, :composers
end

#Fields: first_name:string last_name:string
class Artist < ActiveRecord::Base
  has_and_belongs_to_many :tracks
end

Testing in console:

>> a = Album.new("tracks_attributes"=>{"0"=>{"artists_attributes"=>{"0"=>{"first_name"=>"F
rank","last_name"=>"Pinto"},"1"=>{"first_name"=>"Kevin","last_name"=>"Anthony"}}}})
=> #<Album id: nil, title: nil, release_date: nil, release_location: nil, group_size: nil,
 kind: nil, personnel: nil, notes: nil, created_at: nil, updated_at: nil, cover_file_name:
 nil, cover_content_type: nil>
>> a.tracks
=> [#<Track id: nil, album_id: nil, number: nil, title: nil, duration_in_seconds: nil, cre
ated_at: nil, updated_at: nil>]
>> a.tracks.first.artists
=> [#<Artist id: nil, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: nil,
updated_at: nil>, #<Artist id: nil, first_name: "Kevin", last_name: "Anthony", bio: nil, c
reated_at: nil, updated_at: nil>]
>> a.save
=> true
>> a.tracks.first.artists
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">]
>> a.reload
=> #<Album id: 9, title: nil, release_date: nil, release_location: nil, group_size: nil, k
ind: nil, personnel: nil, notes: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010
-01-24 22:03:59", cover_file_name: nil, cover_content_type: nil>
>> a.tracks.first.artists
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">, #<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at
: "2010-01-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name:
"Kevin", last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2
010-01-24 22:03:59">]

Attempts to Fix

Any attempt to assign a modified array to the object doesn't work:

>> new_artists = a.tracks.first.artists[0,a.tracks.first.artists.length/2]
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">]
>> a.tracks.first.artists = new_artists
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">]
>> a.save
=> true
>> a.reload
=> #<Album id: 9, title: nil, release_date: nil, release_location: nil, group_size: nil, k
ind: nil, personnel: nil, notes: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010
-01-24 22:03:59", cover_file_name: nil, cover_content_type: nil>
>> a.tracks.first.artists
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">, #<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at
: "2010-01-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name:
"Kevin", last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2
010-01-24 22:03:59">]
or:
>> a.tracks.first.artists.uniq!
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">]
>> a.save
=> true
>> a.reload
=> #<Album id: 9, title: nil, release_date: nil, release_location: nil, group_size: nil, k
ind: nil, personnel: nil, notes: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010
-01-24 22:03:59", cover_file_name: nil, cover_content_type: nil>
>> a.tracks.first.artists
=> [#<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at: "2010-0
1-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name: "Kevin",
last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2010-01-24
 22:03:59">, #<Artist id: 9, first_name: "Frank", last_name: "Pinto", bio: nil, created_at
: "2010-01-24 22:03:59", updated_at: "2010-01-24 22:03:59">, #<Artist id: 10, first_name:
"Kevin", last_name: "Anthony", bio: nil, created_at: "2010-01-24 22:03:59", updated_at: "2
010-01-24 22:03:59">]

Any insight into where the issue might be would be much appreciated.

-Frank

Reported by FrankPinto · January 24th, 2010 @ 10:17 PM

State: duplicate
Milestone: none
Assigned to: Mikel Lindsaar Mikel Lindsaar
Importance: Low

Activity

  1. Mikel Lindsaar
    Mikel Lindsaar
    • Assigned user set to Mikel Lindsaar

    Hi Frank,

    Thanks for the bug report. But we need to know what version of rails and ruby you are running this on as well.

    Also, a failing test case would help this get resolved.

    Mikel

    January 24th, 2010 @ 10:23 PM

  2. Zoli
    Zoli

    Hi Mikel,

    I can confirm this bug:
    - Rails 2.3.5 - ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]

    Cannot provide test case but you can find a simple test app attached - please run rake. It's a simple has many through association, created via nested forms (User has many Accounts through AccountUsers). It will create two AccountUsers instead of one.

    This worked perfectly with Rails 2.3.4.

    Zoltan

    January 25th, 2010 @ 01:36 PM

  3. FrankPinto
    FrankPinto

    Hi Mikel,

    Sorry for the delay by Zoltan got it right. My specs are also:
    Rails 2.3.5
    ruby 1.8.6 (2008-08-11 patchlevel 287)[i386-mswin32]

    Let me know what else I could do to get this fixed.

    Thanks,
    Frank

    January 26th, 2010 @ 11:39 PM

  4. Zoli
  5. José Valim
    José Valim
    • State changed from new to duplicate

    February 16th, 2010 @ 11:29 PM