2016-03-03 21 views
2

我是一个在轨道上进行红宝石并开始我的第一个深入应用程序的新人。它有四个表格:问题,选项,答案用户。有一个问题列表,用户可以投票选择一个独特的选项(存储在Answers连接表中),我试图让我的表头关联到表关联。Rails调查样式应用程序 - 在选项上显示所有答案

This is an example of how I'm using the database, minus the Survey and Survey Question

这是我已经设置我的个人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' - 这是正确的方法,我将如何输出关联下的表格行中的总票数选项。

是否需要添加或更改问题控制器代码?

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

感谢

+0

真的令人耳目一新,看到第一个问题很好,但包括所有相关信息。做得好。 – max

+0

啊谢谢 - 我现在非常享受Rails,所以我希望能够坚持下去! – classequalsarthur

回答

1

让我们通过固定起来的关系有点开始:

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查询来获取答案,每个选项的数量。所以我们想要做的是create a counter cache,它在选项表上存储一个标签。

让我们通过创建一个迁移添加列开始:

rails g migration AddAnswerCounterCacheToOptions answers_count:integer 
rake db:migrate 

然后我们告诉ActiveRecord的更新当我们创建相关记录理货,因为counter_cache: true声明是在belongs_to侧这看起来有点怪而专栏是另一个,但多数民众赞成AR的工作原理。

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 

这里有一个小障碍。由于我们可能已经有记录,因此我们需要确保他们有正确的计数器。您可以从控制台执行此操作,但从长远来看,create a rake task是个好主意。

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

这可能需要一些时间,因为它需要拉动每个选项并更新计数。

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

<% 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是足够聪明的使用我们的柜台缓存列,但会回落到查询这是试验一件好事计数。

+0

'counter_cache'的替代方法是编写一个select子句,它在子查询中提取计数。由于您确实需要了解ActiveRecord如何构建查询和加载关系,因此不推荐给初学者。 – max

+0

非常感谢,真的很有用! :-) – classequalsarthur