1

TeamSeasonモデルクラスを含むRailsアプリがあります。このクラスにはhas_oneTeamモデルクラスとの関連付け、およびと呼ばれるhas_many別のクラスとの関連付けがあります。私は今、を渡して、その対戦相手のいずれかがそれに関連付けられているかどうかを判断するメソッドを作成しようとしています。私が書いたメソッドは次のようになります。TeamSeasonopponentsTeamTeam

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

このcountメソッドは、指定したブロックで真の値を生成する配列要素の数をカウントする必要があります。ただし、常に配列の全長を返しているようです。それは、私が指定したブロックが、何があっても常に真の値を生成するかのようです。

putsロジックがどこで間違っているのかを理解するために、さまざまな呼び出しを追加しました。これが私の観察です:

  • countメソッドの横のブロック内に呼び出しを追加するputsと、それらのステートメントの出力が表示されません。ブロックの内容が実行されていないようです

  • 対戦相手の配列の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

これにより、すべての対戦相手が読み込まれるだけでなく、各対戦相手のチームが一度に1つずつ読み込まれ、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 に答える