Hi! I’m a newbie wrapping my head around the Rails way of designing apps
at the database layer, and I’ve hit a minor conceptual logjam and was
hoping some of you might be able to help work me through it.
I’m (re)designing a PHP audio jukebox in RoR (I’m going to be migrating
a big pile of data from a system called Netjuke, which has been folded
into the Jinzora project). I have some very definite ideas about how the
data ought to be structured and how relationships ought to work, and the
metadata schema I’ve designed generates lots of complicated dependencies
and relationships which I feel are best specified and enforced at the
database level. For now I’m working in PostgreSQL, but I might move this
all over to Oracle at some point.
So my toy version of the app has three classes of entities: artists,
albums and tracks. Albums and tracks belong to artists (think
compilations or soundtracks for why that notion of ownership needs to be
at both levels) and tracks also belong to albums. I’m building the
schema via migrations, but have slapped in migrations that look like:
class AddConstraints < ActiveRecord::Migration
def self.up
execute ‘ALTER TABLE tracks ADD FOREIGN KEY(album_id) REFERENCES
albums ON DELETE RESTRICT’
execute ‘ALTER TABLE tracks ADD FOREIGN KEY(artist_id) REFERENCES
artists ON DELETE RESTRICT’
execute ‘ALTER TABLE albums ADD FOREIGN KEY(artist_id) REFERENCES
artists ON DELETE RESTRICT’
end
def self.down
execute ‘ALTER TABLE tracks DROP CONSTRAINT tracks_artist_id_fkey’
execute ‘ALTER TABLE tracks DROP CONSTRAINT tracks_album_id_fkey’
execute ‘ALTER TABLE albums DROP CONSTRAINT albums_artist_id_fkey’
end
end
My problem is that using fixtures and transactional unit tests, I have
to incorporate all the fixtures for the classes in the foreign key
restrictions to ensure that fixtures get set up and torn down correctly.
I.e. unless I have a line that says “fixtures :artists, :albums,
:tracks” in test/unit/(album|artist|track)_test.rb, the test database
isn’t left in a sane state across unit tests and unit tests start
failing due to integrity constraint errors when the fixture code tries
to empty out the table during the fixture setup invoked by the fixtures
method.
It was a bit of an effort to figure all that out, and my solution feels
hacky. Why should I have to set up fixtures for tracks and albums when
I’m only testing artists, who sit at the top of this hierarchy? And
how’s that going to play when I add in many-to-many relationships
between groups (artists) and their members? And glom genres onto this?
It seems like this is going to make my test cases increasingly complex
and unwieldy.
Is it already time for me to abandon using “fixtures” in my test cases
and start doing explicit fixture setup and teardown? Or is there a
simple way I can modify the framework, e.g. to automatically clear out
all of the fixtures used by an individual test case? I can’t imagine I’m
the only person who’s run into this.
Thanks in advance to any insight you might be able to provide. RoR is
totally making it fun for me to work on this project again, and for that
alone I’m very thankful.
Forrest