如何创建基于原有has_many关联的过滤型has_many关联?
问题:基于现有has_many关联创建过滤后的关联
我有一个has_many关联,想创建另一个仅对原有关联结果过滤的has_many关联。现有代码如下:
class Track belongs_to :playlist end class Playlist has_many :tracks has_many :five_star_tracks, -> { what to write here? } has_many :long_tracks, -> { ... } end
请问是否可以实现该需求,还是只能用下面这种方法?
def five_star_tracks tracks.where(rating: 5) end def long_tracks tracks.where("duration_seconds > ?", 600) end
回答
完全可以实现,不用局限于普通方法定义的方式。你只需要在has_many的lambda块里加上过滤条件,同时指定关联的模型类就行(因为关联名称不是模型的复数形式,需要显式声明),具体代码如下:
class Playlist has_many :tracks has_many :five_star_tracks, -> { where(rating: 5) }, class_name: "Track" has_many :long_tracks, -> { where("duration_seconds > ?", 600) }, class_name: "Track" end
两种实现方式的差异:
- 用
has_many定义的是完整的Active Record关联,能直接使用关联专属的方法,比如five_star_tracks.build(...)、five_star_tracks.create(...)或者关联预加载five_star_tracks.includes(:artist),和原tracks关联的用法完全一致。 - 普通方法定义的返回结果是查询集合(ActiveRecord::Relation),虽然能满足查询需求,但没法使用关联特有的构建、创建方法,本质就是对原关联查询的一层封装。
如果需要用到关联的完整功能,优先选has_many加lambda过滤的方式;要是只需要查询过滤后的结果,两种方式都能达到目的。
内容的提问来源于stack exchange,提问作者acanthite
相关产品推荐
相关产品推荐

