SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    inducting songs into a db using has_many :through

    Hi,
    I'm building an app where it reads a dir for files that end with .mp3 and insert them into a db along with the id3 tags in the files.


    my problem is the relationship between the tables. i dont fully understand "has many through" associations yet. i come from a background of 5 years in PHP and i'm only just starting to learn ROR...i know a decent amount of Ruby though.


    this is how i think the structure should be:
    Code:
    class Album < ActiveRecord::Base
        has_one :artist, :through => tracks
        has_many :genres, :through => tracks
        has_many :tracks
    end
    
    class Artist < ActiveRecord::Base
        has_many :albums
        has_many :genres, :through => tracks
        has_many :tracks
    end
    
    class Genre < ActiveRecord::Base
        has_many :albums, :through => tracks
        has_many :artists, :through => tracks
        has_many :tracks
    end
    
    class Track < ActiveRecord::Base
        has_many :albums
        belongs_to :artist
        has_many :genres
    end

    this is how i imagine my tables to look:
    Code:
    # albums table
    create_table :albums do |t|
        t.string :title
        t.integer :track_id
        t.integer :artist_id
    end
    
    # artists table
    create_table :artists do |t|
        t.string :title
        t.integer :track_id
    end
    
    # genres table
    create_table :genres do |t|
        t.string :title
        t.integer :track_id
    end
    
    # tracks table
    create_table :tracks do |t|
        t.string :title
        t.integer :number
        t.integer :genre
        t.datetime :duration
        t.timestamps
    end
    there's a rule that a track or album can only have one artist. if an album happens to have many artists, it will go as 'Various Artists' and if a track has a featured artist for example, it would be a part of the track title.


    is this correct? any suggestions would be great too.
    also, what if a track doesn't belong to an album, how would i go about sorting that out?


    thanks.

  2. #2
    SitePoint Member
    Join Date
    Jul 2007
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Has many through relationships are used when just a simple join table doesn't represent the entire relationship.

    A basic many-to-many relationhip may be as follows:
    users can be in many groups
    groups can have many users
    join table is users_groups, that simply maps users to multiple groups.

    A more advanced relationship appropriate for has many through could be as follows:
    magazines have many readers through subscriptions
    readers are associated to magazines through subscriptions

    Rather than just a simple magazines_readers join table, you would have a table called subscriptions which not only mapped magazines to readers, but also contained data such as subscription start and end date, price, etc.

    To summarize, you use has_many :through when the relationship between two tables contains more data than simply that each record can have many of the other.

    That being said, it is still ok (and probably the standard now) to use has_many through even if its just a simple join relationship, because it gives you the ability to create a third model with a name that makes sense in your business logic. A has_and_belongs_to_many won't have that third model.

  3. #3
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    jeffct, i agree with you.
    i was going to use has_and_belongs_to_many but everybody else told me to use has_many through...almost as if they expect has_and_belongs_to_many to be deprecated in the future.

    however, my question is will my model work? and is it efficient for what i've described?

    thanks.

  4. #4
    SitePoint Enthusiast
    Join Date
    Jun 2008
    Posts
    31
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would put:
    class Artist < ActiveRecord::Base
    has_many :albums
    end

    class Album < ActiveRecord::Base
    belongs_to :artist
    has_many :tracks
    belongs_to :genre
    end

    class Track < ActiveRecord::Base
    belongs_to :album
    end

    class Genre < ActiveRecord::Base
    has_many :albums
    end
    table artists doesn't have a foreign key, table albums has artist_id and genre_id, table tracks has album_id and genres don't have a foreign key

  5. #5
    SitePoint Zealot Koobi's Avatar
    Join Date
    Nov 2003
    Location
    Sri Lanka
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bush34 View Post
    I would put:
    class Artist < ActiveRecord::Base
    has_many :albums
    end

    class Album < ActiveRecord::Base
    belongs_to :artist
    has_many :tracks
    belongs_to :genre
    end

    class Track < ActiveRecord::Base
    belongs_to :album
    end

    class Genre < ActiveRecord::Base
    has_many :albums
    end
    table artists doesn't have a foreign key, table albums has artist_id and genre_id, table tracks has album_id and genres don't have a foreign key


    hey thanks for the suggestion
    but that wont work because i would need to find tracks by genre so there must be a direct many-to-many relationship between tracks and genres.

    also, an album can have many tracks and a track can have many albums.


    for example, a track might appear in an artists regular album but it might also appear in that artsts "Greatest Hits" album. there are many instances like that so i want to be open to that option too.

    thanks for taking the time to reply

  6. #6
    SitePoint Enthusiast
    Join Date
    Jun 2008
    Posts
    31
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK then make a new connector model for example AlbumTrackConnector
    class AlbumTrackConnector < ActiveRecord::Base
    belongs_to :album
    belongs_to :track
    end

    And redefine Album and Track model
    class Album < ActiveRecord::Base
    has_many :album_track_connectors
    has_many :tracks, :through => :album_track_connectors
    end
    class Track < ActiveRecord::Base
    has_manu :album_track_connectors
    has_many :albums, :through => :album_track_connectors
    end

    do the similar for tracks and genres


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •