sql >> Base de Datos >  >> RDS >> Mysql

Aplicación de estilo de encuesta Rails - Mostrar todas las respuestas en la opción

Comencemos arreglando un poco las relaciones:

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

No hay nada técnicamente incorrecto con has_many :answers, :through => :options pero como hay una relación directa a través de answers.question_id no necesitamos pasar por las options tabla para la relación.

Mostrando el conteo

Si simplemente hiciéramos:

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

Esto crearía un desagradable n+1 consulta para obtener el recuento de las respuestas para cada opción. Entonces, lo que queremos hacer es crear un contador de caché que almacena una cuenta en la tabla de opciones.

Comencemos creando una migración para agregar la columna:

rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

Luego le decimos a ActiveRecord que actualice la cuenta cuando creamos registros asociados, esto parece un poco extraño ya que counter_cache: true la declaración está en belongs_to lado mientras que la columna está en el otro, pero así es como funciona 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

Hay un pequeño inconveniente aquí. Dado que es posible que ya tengamos registros, debemos asegurarnos de que tengan los contadores correctos. Puede hacer esto desde la consola, pero a la larga es una buena idea crear una tarea de rake .

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

Esto puede tomar un poco de tiempo ya que necesita extraer cada opción y actualizar el conteo.

Ahora podemos mostrar la cuenta así:

<% 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 es lo suficientemente inteligente como para usar nuestra columna de caché de contadores, pero recurrirá a consultar el conteo, lo cual es bueno para las pruebas.