我根据我在this question的计划建模“特色”,并且遇到了一些绊脚石。
我正在定义一个Song
的主要和特色艺术家:
has_many :primary_artists, :through => :performances, :source => :artist,
:conditions => "performances.role = 'primary'"
has_many :featured_artists, :through => :performances, :source => :artist,
:conditions => "performances.role = 'featured'"
这很好用,除非我正在创建一首新歌,而我通过primary_artist
给它new_song.performances.build(:artist => some_artist, :role => 'primary')
,new_song.primary_artists
不起作用(因为我创建的表演不是还没有保存在数据库中。
这里最好的方法是什么?我正在考虑使用类似的东西:
has_many :artists, :through => :performances
def primary_artists
performances.find_all{|p| p.role == 'primary'}.map(&:artist)
end
答案 0 :(得分:1)
我认为你过度复杂了。仅仅因为事情有相似之处并不意味着你应该把它们放在同一个盒子里。
class Song < ActiveRecord::Base
has_one :artist # This is your 'primary' artist
has_and_belongs_to_many :featured_artists, :source => :artist # And here you make a featured_artists_songs table for the simple HABTM join
validates_presence_of :artist
end
噗,没有混乱。您仍然必须先添加song.artist
才能保存,但这就是您想要的。正确?
答案 1 :(得分:0)
除非您保存,否则您无法识别关联。可以说,在您保存,验证通过以及相关交易完成之前,它确实不存在。
关于清理primary_artist
方法的问题,您可以对此进行建模。
class Song < ActiveRecord::Base
has_many :performances
has_many :artists, :through => :performances
has_one :primary_artist, :through => :performances, :conditions => ["performances.roll = ?", "primary"], :source => :artist
end
目前还不清楚您是否需要一位或多位主要艺术家,但您可以根据需要轻松将has_one
切换为has_many
。
答案 2 :(得分:0)
您已经使用build vs. create确定了问题的根源。
至于寻找一首歌的主要艺术家。我会在艺术家上添加一个named_scope来选择特色/主要艺术家。
class Artist < ActiveRecord::Base
...
named\_scope :primary, :joins => :performances, :conditions => "performances.role = primary"
named\_scope :featured, :joins => :performances, :conditions => "performances.role = featured"
end
要获得一首歌的主要艺术家,你可以选择@ song.artists.primary或者你喜欢歌曲中的primary_artists方法。
def primary_artists
artists.primary
end
但是,在查看了您的初始问题后,我认为您的数据库布局不足。这是可行的,但不清楚,I've posted my suggestions there, where it belongs.
这些命名的范围我也可以在我提出的方案下工作。