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