Rails survey style application - Show all answers on option

人走茶凉 提交于 2019-12-12 17:26:25

问题


I'm a new guy to ruby on rails and working on my first in-depth application. It has four tables: Questions, Options, Answers and Users. There's a list of questions and a user can vote for a unique option (stored in the Answers join table), I'm trying to get my head around table associations.

This is how I've setup my individual RB files:

class Question < ActiveRecord::Base
     has_many :options
     has_many :answers, :through => :options
end

class Option < ActiveRecord::Base
    belongs_to :question
    has_many :answers
end

class Answer < ActiveRecord::Base
    belongs_to :user
    belongs_to :question
    belongs_to :option
end

class User < ActiveRecord::Base
    has_many :answers
    has_many :questions, :through => :answers 
end

My questions controller is setup like this to include the options table:

@questions = Question.includes(:options).all

and the table body in my index.html.erb file:

<tbody>
   <% @questions.each do |question| %>
      <tr class="<%= cycle('lineOdd', 'lineEven') %>">
         <td><%= question.question_text %></td>
         <td><%= link_to 'Show', question %></td>
         <td><%= link_to 'Edit', edit_question_path(question) %></td>
         <td><%= link_to 'Destroy', question, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
      <% question.options.each do |option_text| %>
         <tr class="backgroundColor1">
            <td class="optionCell"> <%= option_text.option_text %> </td>
         </tr>
      <% end %>
   <% end %>
</tbody>

In the Question class I've used 'has_many :answers, :through => :options' - is this the correct way to go about this and how would I output the total number of votes in a table row below the associated option.

Do I need to add to or change the question controller code?

This is my first post, sorry if I'm not informative enough!

Thanks


回答1:


Lets start by fixing up the relations a bit:

class Question < ActiveRecord::Base
  has_many :options
  has_many :answers
  has_many :users, through: :answers
end

There is nothing technically wrong with has_many :answers, :through => :options but since there is a direct relation through answers.question_id we don't need to go through the options table for the relation.

Displaying the count

If we simply did:

<td class="optionCell"><%= option.answers.count %></td>

This would create a nasty n+1 query to fetch the count of the answers for each option. So what we want to do is create a counter cache which stores a tally on the options table.

Lets start by creating a migration to add the column:

rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

Then we tell ActiveRecord to update the tally when we create associated records, this looks a bit strange since the counter_cache: true declaration is on the belongs_to side while the column is on the other but thats just how AR works.

class Option < ActiveRecord::Base
  belongs_to :question
  has_many :answers
end

class Answer < ActiveRecord::Base
  belongs_to :user
  belongs_to :question
  belongs_to :option, counter_cache: true
end

There is a little snag here. Since we may already have records we need to make sure they have correct counters. You can do this from the console but in the long run it is a good idea to create a rake task.

Option.find_each { |option| Option.reset_counters(option.id, :answers) }

This might take a bit of time since it needs to pull each Option and update the count.

Now we can display the tally like so:

<% question.options.each do |option| %>
  <tr class="backgroundColor1">
    <td class="optionCell"><%= option.option_text %></td>
    <td class="optionCell"><%= option.answers.size %></td>
  </tr>
<% end %>

.size is smart enough to use our counter cache column, but will fall back to querying the count which is a good thing for tests.



来源:https://stackoverflow.com/questions/35771847/rails-survey-style-application-show-all-answers-on-option

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!