Задачи моделирования понятия «Избранные артисты» (о рэп-песнях) - PullRequest
0 голосов
/ 06 ноября 2010

Иногда рэп-песни имеют более одного исполнителя.Например, «Месть Романа» Ники Минажа содержит Эминема и, таким образом, появляется в качестве «Мести Романа» (Месть Романа) в каталогов Rap Genius .

В Rap Genius I модель представлена ​​художниками через performances модель соединения, которая имеет следующие атрибуты:

  • song_id
  • artist_id
  • role («основной» или «рекомендуемый»)

Итак:

  • In 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

Но это все равно кажется немного запутанным / хакерским.

1 Ответ

0 голосов
/ 06 ноября 2010

Немного другая идея, но не было бы немного проще и понятнее иметь здесь два отношения между исполнителями и песнями, то есть песня имела бы отношения с исполнителями по типу:

belongs_to :primary_artist,                :class_name => "Artist"
has_and_belongs_to_many :featured_artists, :class_name => "Artist"
...