轨道上的红宝石 - 无法让 Array 的计数方法与块一起使用



我有一个Rails应用程序,它包含一个TeamSeason模型类。该类具有与Team模型类的has_one关联,以及与另一个称为opponentsTeamSeasonhas_many关联。我现在正试图编写一个方法,该方法传入一个Team,并确定它的任何对手是否与该Team关联。我写的方法看起来像这样:

def plays?(against_team)
  total = opponents.count {|opponent| opponent.team == against_team}
  return (total > 0)
end

count方法应该计算使用指定的块I生成真值的数组元素的数量。但是,它似乎总是返回数组的完整长度。就好像我指定的块总是产生一个真值,不管怎样。

我添加了各种puts调用,试图找出我的逻辑哪里出了问题。以下是我的观察结果:

  • 当我在count方法旁边的块中添加任何puts调用时,我看不到这些语句的任何输出。块的内容似乎从未被执行

  • 当我使用对手数组的each方法和一个块插入一个额外的循环时,我可以打印我的数组对象的值,并确认它们的计算结果符合我的预期。我甚至可以puts opponent.team == against_team的值,并验证我编写的块在某些时候是否评估为false,这是应该的。

我在这里错过了什么?

opponents不是一个标准的ruby数组,它是一个ActiveRecord关联代理,对于某些方法表现不同。count将在数据库中查询对手的数量,并且不会评估您正在通过的阻挡。做你想做的事情的一种更简单的方法是这样的:

def plays?(against_team)
  opponents.joins(:team).where(teams: {id: against_team.id}).exists?
end

这将询问数据库你想要什么,并避免在你只检查特定比赛时加载所有对手。或者,您可以加载整个对手列表并使用any?:

def plays?(against_team)
  opponents.any?{|opponent| opponent.team == against_team.id}
end

请注意,这不仅会加载所有对手,还会一次加载每个对手的团队,从而导致N+1查询(这会导致性能问题)。您可以通过使用includes():加载相关团队来避免这种情况

opponents.includes(:team).any?{...}

您正在尝试的功能可以使用include?方法来实现。

尝试:

def plays?(against_team)
  opponents.collect(&:team).include?(against_team)
end

相关内容

  • 没有找到相关文章

最新更新