Rails调查样式应用程序-在选项上显示所有答案 [英] Rails survey style application - Show all answers on option

查看:83
本文介绍了Rails调查样式应用程序-在选项上显示所有答案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个红宝石新手,正在从事我的第一个深度应用程序.它有四个表:问题选项答案用户.有一个问题列表,用户可以投票给一个唯一的选项(存储在答案"联接表中),我正设法弄清表关联.

这是我设置单个RB文件的方式:

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

我的问题控制器的设置如下,以包括选项表:

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

和index.html.erb文件中的表主体:

<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>

在Question类中,我使用了'has_many:answers,:through =>:options'-这是解决此问题的正确方法,以及如何在关联下方的表格行中输出投票总数选项.

我需要添加或更改问题控制器代码吗?

这是我的第一篇文章,对不起,如果我没有足够的信息!

谢谢

解决方案

让我们首先修复一下关系:

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

has_many :answers, :through => :options在技术上没有任何问题,但是由于通过answers.question_id存在直接关系,因此我们不需要遍历options表即可.

显示计数

如果我们只是这样做:

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

这将创建一个令人讨厌的n+1查询,以获取每个选项的答案计数.因此,我们要做的是创建计数器缓存,该计数器将提示符存储在选项表.

首先创建一个迁移以添加列:

rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

然后我们告诉ActiveRecord在创建关联记录时更新计数,这看起来有点奇怪,因为counter_cache: true声明位于belongs_to侧,而列位于另一侧,但这就是AR的工作方式./p>

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

这里有一点障碍.由于我们可能已经有记录,因此我们需要确保它们具有正确的计数器.您可以从控制台执行此操作,但从长远来看,最好创建一个耙任务.

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

这可能需要一些时间,因为它需要拉出每个Option并更新计数.

现在我们可以像这样显示提示:

<% 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足够聪明,可以使用我们的计数器缓存列,但会回退到查询计数,这对于测试是件好事.

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

解决方案

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.

这篇关于Rails调查样式应用程序-在选项上显示所有答案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆