0

What's the best way to do this? I want to be able to give Bands and Artists genres through polymorphism. I can do it with habtm and has_many :through but I'm trying to figure out if it's possible through polymorphism.

GenreList would be a lookup table with a list of different genres (e.g. Punk, Pop, Metal). I've reviewed Ryan Bate's screencast for Polymorphic Assoiciations but I'm still stuck. Specifically, I'm not sure how to create the polymorphic table Genre which would be fed canned genres from the GenreList model (the lookup table).

Is the following correct?

rails generate model Genre genre_list_id:integer genreable_id:integer genreable_type:string

class Artist < ActiveRecord::Base
  has_many :genres, :as => :genreable
end

class Band < ActiveRecord::Base
  has_many :genres, :as => :genreable
end

class Genre < ActiveRecord::Base
  belongs_to :genreable, :polymorphic => true
end

class GenreList < ActiveRecord::Base
end
face7hill
  • 11
  • 3

3 Answers3

1

I think your implementation is a little bit weird. The way I would do it is to create a model Genre (which it will hold all the available genres Punk, Rock, Metal etc). Then I would do all this that you've already done but without the GenreList model:

rails g model Genre genreable_id:integer genreable_type:string genre_name:string

class Artist < ActiveRecord::Base
   has_many :genres, :as => :genreable
end

class Band < ActiveRecord::Base
  has_many :genres, :as => :genreable
end

class Genre < ActiveRecord::Base
   belongs_to :genreable, :polymorphic => true
end

Then I would do make some nested resources in my routes as:

resources :artists do
  resources :genres
end

resources :bands do
  resources :genres
end

and then edit my controller to handle this nested relation. With this approach say if i want to see all the genres of the first artist I would visit:

/artists/1/genres

same holds for bands. I hope that I understood your problem. Let me know if I helped!

Gerry
  • 5,326
  • 1
  • 23
  • 33
  • xlubyonrails, sorry for my late response. I'm still slogging through this. Your answer is helpful but I'm really trying to keep the Genre List in it's own table for referential integrity. I only want to store the genre_list_ids in the polymorphic table. This is starting to be trickier than I anticipated. Basically, when I add/edit an Artist or Band, I want to be able to check off the genres in one fell swoop and store the genres in the genre polymorphic table. I'm looking at inherited_resources to see if that helps simplify. I'll post my results if I make progress. Thanks! – face7hill Feb 09 '11 at 00:37
1

Ok, after 6.5 hrs, I managed to figure this out. I used the inherited_resources gem to help with the controllers. To recap, I wanted to be able to add Genres to Artists and Bands through a polymorphic relationship, i.e. Genres would be a lookup table, and Genreings would be a polymorphic model that contains genres for Artists and Bands. Below is the code that worked for me:

# Generate some scaffolding
rails generate scaffold Artist name:string
rails generate scaffold Band name:string
rails generate scaffold Genre name:string
rails generate scaffold Genreing genre_id:integer genreable_id:integer genreable_type:string

# Models  
class Artist < ActiveRecord::Base
    has_many :genreings, :as => :genreable
    has_many :genres, :through => :genreings
end

class Band < ActiveRecord::Base
    has_many :genreings, :as => :genreable
    has_many :genres, :through => :genreings
end

class Genre < ActiveRecord::Base
    attr_accessible :name
    has_many :genreings
end

class Genreing < ActiveRecord::Base
    attr_accessible :genre, :genre_id, :genreable, :genreable_type, :genreable_id
    belongs_to :genre
    belongs_to :genreable, :polymorphic => true
end

# Controller
class GenreingsController < InheritedResources::Base
    belongs_to :genreable, :polymorphic => true
end

# Artist Form View
= simple_form_for(@artist) do |f|

  .inputs
    = f.input :name
    = f.association :genres, :as => :check_boxes

  .actions
    = f.button :submit

# Band Form View
... (Similar to Artist)
face7hill
  • 11
  • 3
0

It is correct. One thing that seems to be missing is the has_many relationship from GenreList to Genre

class GenreList < ActiveRecord::Base
  has_many :genres
end
Stephan
  • 2,853
  • 3
  • 20
  • 25
  • Stephan, thanks for this. Now I'm trying to sort through the views and controllers to make it actually work. – face7hill Feb 09 '11 at 00:32