How to model the concept of "Featuring" (ie when an artist is "shown" on a song)
Sometimes there may be more than one artist per song. For example, Jay-z's new song "A Star Is Born" includes the artist Cole and will thus appear as "Jay-z (featuring Cole) -" A Star Is Born "in the catalog. My question is how to simulate this in my database.
It's pretty simple now: every song belongs_to :artist
and every artist has_many :songs
. I want to change this so that there are many artists in the songs, with one artist listed as "primary" ie. If A, B, and C are associated with a given song, and A is the primary, the artist for that song will be displayed as "A (featuring B and C)".
That's what I think:
Song:
has_many :artists, :through => :performances
Executor:
has_many :songs, :through => :performances
where the model performance
would have one field for primary?
, determining if a given performance is the "main" performance in the song, meaning that the artist associated with that performance is the main performer of the song.
Does this approach make sense?
source to share
It looks like you are using the performances as a join table with added information to link songs to artists. But that doesn't work well enough. Songs can have multiple performances, and each performance can have multiple artists.
I would restructure the database to use the following structure. Unfortunately it takes a little more work to add the Song to the database, but it allows for covers, multiple versions of the song and duets.
Song (Attributes: Title)
- has many designs
- has many performers (through execution)
- has many artists (via performers)
Performance (foreign key: Song_id, attributes: date, year, length, genre, album)
- belongs to Song
- has many performers
- has many performers (through performers)
Artists (Foreign Keys: Performance_id, Artist_id, Attributes: Role)
- has one song (via artists) NB has_one: via is not a core feature of Rails
- belongs to execution
- owned by Artist
Artist (attributes: name, date of birth, etc.) (other personal data)
- has many performers
- has many performances (through performers)
- has many songs (through performance)
If you want to force 1 main performer / performance, it will be done as confirmation in Performers.
class Performers < ActiveRecord::Base
validates_uniqueness_of :role, :scope => [:performance_id], :if => Proc.new{|performer| performer.role == "primary"}
end
source to share