2012-03-09 11 views
3

私のウェブサイトのユーザーは、彼の友人が異なる質問で彼に与えた回答の平均(1〜100)を知りたいと思っています。Ruby on Railsのループ内ループループ

この方法の最終結果は[質問、すべての答えの合計、回答数]

3表は、私はテーブルを持って、独自のコントローラとモデル

で各1関与しているとの配列ですユーザーと友人を格納する「友情」の

質問の一覧があり、質問とそのIDだけがあります。

最後に私は友人ID、質問ID、および答えを格納するanswersテーブルを持っています。

私はそれをやる方法を見つけました(まだ試していません):ユーザーの友情を探してから、これらの友情のそれぞれの回答を探して、それを追加する最終的なアレイに移す。

q_and_a = Array.new 
friendships = Friendship.find_by_user_id(current_user.id) 
friendships.each do |friendship| 
    answers = Answer.find_by_friendship_id(friendship.id) 
    answers.each do |answer| 
     q_and_a.each do |array| 
      question = Question.find_by_id(answer.question_id) 
      if array[0] == statement.description 
       array[1] = array[1] + answer.value 
       array[2] = array[2] + 1 
      else 
       q_and_a << [ question.description, answer.value, 1 ] 
      end 
     end 
    end 
end 

私は恐ろしいですが、これを行うには良い方法があると思いますか?さらに友情テーブル、などの回答テーブルは、レコードの数十万人を持っているにバインドされ、成長し続けることを考えると

編集 後述するように、私は協会が設定していたが、私はでしたそれらを使用していない!ルーキーミス。

@q_and_a_them = Array.new 
user_answers = current_user.friends.collect { |c| c.answers }.flatten 
user_answers.each do |a| 
    question = Question.find_by_id(a.question_id) 
    if @q_and_a_them.empty? 
    @q_and_a_them << [ question.description, a.value, 1 ] 
    else 
    @q_and_a_them.each do |q| 
     if q[0] == question.description 
     q[1] = q[1] + a.value 
     q[2] = q[2] + 1 
     else 
     @q_and_a_them << [ question.description, a.value, 1 ] 
     end 
    end 
    end 
end 

プラスfriendship.rb

has_many :relationships 
has_many :answers, :through => :relationships 
+0

バックエンドは従来のSQLデータベースですか?これは潜在的に "規模の"問題を引き起こす可能性があり、潜在的にこれを最適化して、最終的に "ほぼ"リアルタイムで一貫した/更新される別個の "friendship_stats"テーブルを有する。 – Pete

+0

それはsqlite3です、私は開発を始めています。上のコードを常にバックグラウンドで実行している 'friendship_stats'テーブルが必要ですか? – wachichornia

+0

必ずしも「すべての時間」である必要はなく、バックグラウンドではある程度の間隔をおいて、ユーザーにはこれについての最新のバージョンが表示されます。あなたがログインするたびにSOの評判が再計算されないのと同じように、一度計算してキャッシュするのが理にかなっています。 – Pete

答えて

1

まあ

friendships.answers.each 

あなたの関係が正しく設定されている場合(has_many、belongs_to)

0

上の設定は、内部ロジックはもう少し複雑ですが、#flat_mapを使用して深さの1つのレベルを減らすことができます: 最終作業コードです

friendships.flat_map { |f| Answer.find_by_friendship_id f.id }.each do |answer| 
    q_and_a.each do |array| 
    # Blah blah. 
    end 
end