3

I want the user of my website to see the average of the answers (1 to 100) his friends have given him on different questions.

The final result of this method is an array with [question, sum of all answers, answer count]

3 tables are involved, each one with its own controller and model

I have a table of 'friendships', which stores users and friends.

Then there is a table of questions, which have just the questions and its ids.

Finally I have an answers table, which stores the friendship id, the question id and the answer given.

I found a way to do it (haven't tried it yet though): I look for the friendships of the user, then look for the answers given by each of these friendships, then going through each question to add it to a final array.

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

Its horrible, I'm hoping there is a better way to do this? Even more considering that the friendships table, as well as the answers table, are bound to have hundreds of thousands of records and will continue to grow

Edit As stated below, I had the associations set up but i was not using them! rookie mistake. The final working code is:

@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

Plus the config on friendship.rb

has_many :relationships
has_many :answers, :through => :relationships
5
  • Is your backend a traditional SQL database? This does potentially present a problem "at scale", which would lead to potentially optimizing this w/ a separate "friendship_stats" table that is eventually consistent/updated in "near" realtime. Commented Mar 9, 2012 at 16:21
  • it is an sqlite3, I'm starting the development. You mean I should have a 'friendship_stats' table that is running the code above in the background all the time? Commented Mar 9, 2012 at 17:00
  • Not necessarily "all the time", but at some interval in the background such that users would see a roughly-up-to-date version of this. Much the same way a user's reputation on SO isn't recalculated every time you log in, some things make sense to compute once and cache. Commented Mar 9, 2012 at 17:33
  • What is statement.description? Commented Mar 9, 2012 at 17:50
  • statement.description is question.description. Thanks Pete Commented Mar 10, 2012 at 13:09

2 Answers 2

1

Well

friendships.answers.each

should work, given that you have your relationships set up correctly (has_many, belongs_to)

Sign up to request clarification or add additional context in comments.

Comments

0

The inner logic is a little more complicated, but you can reduce one level of depth using #flat_map:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.