在Rails中,如何计算集合中关联记录的数量?

THp*_*ubs 2 ruby ruby-on-rails ruby-on-rails-4

我有一个名为的模型Awardunit.Awardunit有很多Awardleaders.一个奖励单位可以有一个或多个奖项领导者.

如果我获得所有记录或搜索并获取一个名为变量的记录集合,awardunits我该如何计算Awardleaders该集合中所有单位的数量?

这是我做的:

 @leaders = 0
 @awardunits.each do |unit|
      @leaders = @leaders + unit.awardleaders.size
 end
Run Code Online (Sandbox Code Playgroud)

再次计算残疾领导者我用这个:

  @disabledleaders = 0
  @awardunits.each do |unit|
     @disabledleaders = @disabledleaders + unit.awardleaders.where(disabled: true).size
  end
Run Code Online (Sandbox Code Playgroud)

如果我使用它,每次页面加载时都必须经过所有记录.这样做有没有更好的方法?

jan*_*oeh 8

您可以通过添加计数器缓存来便宜地计算关联:

class AwardUnit << ActiveRecord::Base
  has_many :award_units
end

class AwardLeader << ActiveRecord::Base
  belongs_to :award_unit, counter_cache: true
end
Run Code Online (Sandbox Code Playgroud)

现在添加一个名为新列award_leaders_count到你AwardUnit在一个新的迁移表:

  def change
    add_column :award_units, :award_leaders_count, :integer, default: 0

    AwardUnit.all.each do |unit|
      AwardUnit.reset_counters(unit.id, :award_leaders)
    end
  end
Run Code Online (Sandbox Code Playgroud)

Rails现在将自动缓存每个的award_leaders数量,AwardUnit@my_award_unit.award_leaders.count在不运行其他数据库查询的情况下为您提供计数.

默认情况下,Rails counter_cache仅适用于所有award_leaders.如果您只需要计算那些有条件的award_leader,您将需要添加自己的counter_cache:

class AwardUnit << ActiveRecord::Base
  has_many :award_units
end

class AwardLeader << ActiveRecord::Base
  belongs_to :award_unit

  scope :disabled, -> { where(disabled: true) }

  after_save :update_counter_cache
  after_destroy :update_counter_cache

  def update_counter_cache
    award_unit.update_attribute(:disabled_award_units_count, award_unit.award_leaders.disabled.count)
  end
end
Run Code Online (Sandbox Code Playgroud)

移民:

  def change
    add_column :award_units, :disabled_award_leaders_count, :integer, default: 0

    AwardUnit.all.each do |unit|
      unit.update_attribute(:disabled_award_units_count, unit.award_leaders.disabled.count)
    end
  end
Run Code Online (Sandbox Code Playgroud)

现在,当你拥有一系列AwardUnits时,获得残疾奖励领导者的总数就像这样简单

@award_units = AwardUnit.limit(5).to_a # or a similar query
@award_units.inject(0){|sum,unit| sum + unit.disabled_award_leaders_count }
Run Code Online (Sandbox Code Playgroud)