使用带有子模型计数的named_scope

我有一个有很多孩子的简单父对象。 我正在试图弄清楚如何使用命名范围来恢复具有特定数量的孩子的父母。

这可能吗?

class Foo  1 end class Bar < ActiveRecord::Base belongs_to :foo end 

我希望做一些像Foo.with_one_bar这样的事情

我可以在父类上编写类似这样的方法,但我宁愿拥有命名范围的强大function

 class Foo < ActiveRecord::Base has_many :bars # I don't like having the number be part of the name, but you asked for it. named_scope :with_one_bar, :joins => :bars, :group => "bars.foo_id", :having => "count(bars.foo_id) = 1" # More generically... named_scope :with_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) = ?", n]}} named_scope :with_gt_n_bars, lambda {|n| {:joins => :bars, :group => "bars.foo_id", :having => ["count(bars.foo_id) > ?", n]}} end 

像这样打电话:

 Foo.with_n_bars(2) 

我会使用计数器缓存 。 因此,您需要以下迁移:

 class AddBarCount < ActiveRecord::Migration def self.up add_column :foos, :bars_count, :integer, :default => 0 Foo.reset_column_information Foo.all.each do |p| p.update_attribute :bars_count, p.bars.length end end def self.down remove_column :foos, :bars_count end end 

比你需要的更改你这样的Bar模型:

 class Bar < ActiveRecord::Base belongs_to :foo, :counter_cache => true end 

现在, bars被缓存在foo模型中,这将加快查询bars

你的named_scopes看起来也是这样的:

 #rails 2 named_scope :with_no_bars, :conditions => { :bars_count => 0 } named_scope :with_one_bar, :conditions => { :bars_count => 1 } named_scope :with_more_than_one_bar, :conditions => ["bars_count > 1"] #rails 3 & ruby 1.9+ scope :with_no_bars, where(bars_count: 0) scope :with_one_bar, where(bars_count: 1) scope :with_more_than_on_bar, where("bars_count > 1") #rails 4* & ruby 1.9+ scope :with_no_bars, -> { where(bars_count: 0) } scope :with_one_bar, -> { where(bars_count: 1) } scope :with_more_than_one_bar, -> { where("bars_count > 1") } 

这样,每次发出此类请求时,您都可以为每个foo节省计算bars的时间。

我有这个想法观看关于计数器缓存的railscast: http ://railscasts.com/episodes/23-counter-cache-column

* Active Record中的新function[2013年Rails 4倒计时]