无法使用Array的count方法来处理块

时间:2013-02-07 03:52:59

标签: ruby-on-rails ruby ruby-on-rails-3

我有一个包含TeamSeason模型类的Rails应用程序。此类与has_one模型类具有Team关联,与另一个名为has_many的{​​{1}}具有TeamSeason关联。我现在正在尝试编写一个传递opponents的方法,并确定其任何对手是否与Team相关联。我写的方法看起来像这样:

Team

def plays?(against_team) total = opponents.count {|opponent| opponent.team == against_team} return (total > 0) end 方法应该计算使用我指定的块产生true值的数组元素的数量。但是,它似乎总是返回数组的全长。这就好像我指定的块总是产生一个真值,无论如何。

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

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

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

我在这里缺少什么?

2 个答案:

答案 0 :(得分: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?{...}

答案 1 :(得分:0)

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

尝试:

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