Thanks Josh! It works! (mostly) I was able to create a many to many
association with the two parents and the join table, though it looks
like the Album and Artist factories are created twice each, which is
my next task, though it probably won't impact testing... You
definitely pointed me in the right direction, creating the factory
associations from the join table to the parents rather than from the
parents to the join table. I've added some comments to help others
with similar issues.
<script-console-output>
$> RAILS_ENV=test script/console
Loading test environment (Rails 2.3.2)
>> @artists = Artist.find(:all)
=> [#<Artist id: 8, name: "FooFighters", created_at: "2009-05-22
17:53:01", updated_at: "2009-05-22 17:53:01">,
#<Artist id: 9, name: "FooFighters", created_at: "2009-05-22
17:53:01", updated_at: "2009-05-22 17:53:01">]
>> @albums = Album.find(:all)
=> [#<Album id: 6, genre: "FooRock", name: "FooTime", description: "A
good time", created_at: "2009-05-22 17:53:01", updated_at: "2009-05-22
17:53:01">,
#<Album id: 7, genre: "FooRock", name: "FooTime", description: "A good
time", created_at: "2009-05-22 17:53:01", updated_at: "2009-05-22
17:53:01">]
>> @features = Feature.find(:all)
=> [#<Feature id: 7, artist_id: 8, album_id: 6, number_of_songs: nil,
created_at: "2009-05-22 17:53:01", updated_at: "2009-05-22 17:53:01">]
>
</script-console-output>
Here is a dump of the sqlite3 tables using 'RAILS_ENV=test script/
dbconsole'
<sqlite3-output>
CREATE TABLE "artists" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT
NULL, "name" varchar(255), "created_at" datetime, "updated_at"
datetime);
INSERT INTO "artists" VALUES(8,'FooFighters','2009-05-22
17:53:01','2009-05-22 17:53:01');
INSERT INTO "artists" VALUES(9,'FooFighters','2009-05-22
17:53:01','2009-05-22 17:53:01');
CREATE TABLE "albums" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT
NULL, "genre" varchar(255), "name" varchar(255), "description" varchar
(255), "created_at" datetime, "updated_at" datetime);
INSERT INTO "albums" VALUES(6,'FooRock','FooTime','A good
time','2009-05-22 17:53:01','2009-05-22 17:53:01');
INSERT INTO "albums" VALUES(7,'FooRock','FooTime','A good
time','2009-05-22 17:53:01','2009-05-22 17:53:01');
CREATE TABLE "features" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT
NULL, "artist_id" integer, "album_id" integer, "number_of_songs"
integer, "created_at" datetime, "updated_at" datetime);
INSERT INTO "features" VALUES(7,8,6,NULL,'2009-05-22
17:53:01','2009-05-22 17:53:01');
</sqlite3-output>
Here is the revised code
<code>
# models
class Artist < ActiveRecord::Base
has_many :features
has_many :albums, :through => :features
end
class Album < ActiveRecord::Base
has_many :features
has_many :artists, :through => :features
end
class Feature < ActiveRecord::Base
belongs_to :album
belongs_to :artist
end
# revised factories
# created the associations from the join table only
Factory.define(:artist) do |artist|
artist.name "FooFighters"
end
Factory.define(:album) do |album|
album.name "FooTime"
album.genre "FooRock"
album.description "A good time"
end
# join table factory - :feature
Factory.define(:feature) do |feature|
feature.association :artist
feature.association :album
end
# features/support/env.rb # cucumber environment file used to setup
factories
Before do
#killing the table data as we aren't using fixtures
Album.destroy_all
Artist.destroy_all
Feature.destroy_all
#recreating the data
# **** Here's the magic ****
# building the parent factories first, and saving them
# after the join table record is fully created in db
album = Factory.build(:album)
artist = Factory.build(:artist)
# using create here as the join table is written to
# the db first with id's from album and artist factories.
# you could use 'feature = Factory(:feature)'
# though using 'create' method for clarity.
feature = Factory.create(:feature)
album.save
artist.save
end
</code>
Thanks again,
Dave