2010-11-05 59 views
0

有时候说唱歌曲有不止一位艺术家。例如,Nicki Minaj's "Roman's Revenge"功能Eminem,因此在Rap Genius类别记录中显示为“Nicki Minaj(Ft。Eminem) - Roman's Revenge”。建模“有特色的艺术家”概念的问题(说唱歌曲)

说唱天才I型特色通过performances艺术家加入具有以下属性型号:

  • song_id
  • artist_id
  • role(无论是 “主” 或 “特色”)

所以:

  • artist.rb

    has_many :songs, :through => :performances 
    
  • song.rb

    has_many :artists, :through => :performances 
    

song.rb

def primary_artists 
    performances.select{|p| p.role == 'primary'}.map(&:artist).compact 
end 

def featured_artists 
    performances.select{|p| p.role == 'featured'}.map(&:artist).compact 
end 

# from the user's perspective there's only one primary artist 
def primary_artist 
    primary_artists.first 
end 

问题是如何实施Song#primary_artist=Song#featured_artists=。现在,我这样做,这是越野车:

def primary_artist=(artist) 
    return if artist.blank? 
    Performance.song_id_eq(id).role_eq('primary').destroy_all 

    performances.build(:artist => artist, :role => 'primary') 
end 

其原因,这是越野车的是,这种方法会破坏现场的所有现有主要艺术家,但是当歌曲被保存只创建了更换主艺术家。所以,如果歌曲保存失败,它的主要艺术家将被删除。

什么是正确的方法来做到这一点?我们希望只有在乐曲保存成功将删除旧的主要艺术家,所以一个想法是:

def primary_artist=(artist) 
    return if artist.blank? 
    #Performance.song_id_eq(id).role_eq('primary').destroy_all 
    @performances_to_destroy << Performance.song_id_eq(id).role_eq('primary') 

    performances.build(:artist => artist, :role => 'primary') 
end 

def after_save 
    @performances_to_destroy.each(&:destroy) 
end 

但这似乎仍有点混乱/ hackish的。

+1

我不明白为什么你要限制用户看到的主要艺术家。如果您只显示所有相关艺术家,您的问题不会消失吗? – John 2010-11-05 21:31:10

+0

不是 - 虽然我现在认识到我的问题的核心比上面简单。见http://stackoverflow.com/questions/4111345/save-changes-to-a-has-many-association-only-when-you-successfully-save-the-parent – 2010-11-06 01:06:56

回答

0

稍有不同的想法,但不会是一个有点简单和清晰有艺术家和歌曲之间的两个关系在这里,即一首歌会有线沿线的艺术家的关系:

belongs_to :primary_artist,    :class_name => "Artist" 
has_and_belongs_to_many :featured_artists, :class_name => "Artist" 
相关问题