Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Aplicação de estilo de pesquisa Rails - Mostrar todas as respostas na opção


Vamos começar corrigindo um pouco as relações:
class Question < ActiveRecord::Base
  has_many :options
  has_many :answers
  has_many :users, through: :answers
end

Não há nada tecnicamente errado com has_many :answers, :through => :options mas como existe uma relação direta através de answers.question_id não precisamos passar pelas options tabela para a relação.

Exibindo a contagem


Se simplesmente fizéssemos:
<td class="optionCell"><%= option.answers.count %></td>

Isso criaria um desagradável n+1 query para buscar a contagem das respostas para cada opção. Então, o que queremos fazer é criar um cache de contador que armazena uma contagem na tabela de opções.

Vamos começar criando uma migração para adicionar a coluna:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

Em seguida, dizemos ao ActiveRecord para atualizar a contagem quando criamos registros associados, isso parece um pouco estranho, pois o counter_cache: true declaração está no belongs_to lado enquanto a coluna está do outro, mas é assim que o AR funciona.
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

Há um pequeno problema aqui. Como já podemos ter registros, precisamos garantir que eles tenham contadores corretos. Você pode fazer isso no console, mas a longo prazo é uma boa ideia criar uma tarefa de rake .
Option.find_each { |option| Option.reset_counters(option.id, :answers) }

Isso pode demorar um pouco, pois precisa puxar cada Option e atualizar a contagem.

Agora podemos exibir a contagem assim:
<% 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 é inteligente o suficiente para usar nossa coluna de cache de contador, mas voltará a consultar a contagem, o que é bom para testes.