1

我有一个包含TeamSeason模型类的 Rails 应用程序。该类has_oneTeam模型类有关联,并has_many与另一个TeamSeason称为opponents. 我现在正在尝试编写一个传入 aTeam并确定它的任何对手是否与它相关联的方法Team。我写的方法是这样的:

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

count方法应该计算在我指定的块中产生真值的数组元素的数量。但是,它似乎总是返回数组的全长。就好像我指定的块总是产生一个真实的值,无论如何。

我添加了各种puts调用来尝试找出我的逻辑出错的地方。以下是我的观察:

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

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

我在这里想念什么?

4

2 回答 2

3

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?{...}
于 2013-02-07T04:03:40.753 回答
0

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

尝试:

def plays?(against_team)
  opponents.collect(&:team).include?(against_team)
end
于 2013-02-07T04:02:36.273 回答