Mysql
 sql >> Database >  >> RDS >> Mysql

Applicazione in stile sondaggio Rails - Mostra tutte le risposte su opzione

Cominciamo col sistemare un po' le relazioni:

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

Non c'è niente di tecnicamente sbagliato in has_many :answers, :through => :options ma poiché esiste una relazione diretta tramite answers.question_id non abbiamo bisogno di passare attraverso le options tabella per la relazione.

Visualizzazione del conteggio

Se lo facessimo semplicemente:

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

Questo creerebbe un brutto n+1 query per recuperare il conteggio delle risposte per ciascuna opzione. Quindi quello che vogliamo fare è creare una cache del contatore che memorizza un conteggio nella tabella delle opzioni.

Iniziamo creando una migrazione per aggiungere la colonna:

rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate

Quindi diciamo ad ActiveRecord di aggiornare il conteggio quando creiamo record associati, questo sembra un po' strano poiché counter_cache: true la dichiarazione è su belongs_to lato mentre la colonna è sull'altro, ma è proprio così che funziona 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

C'è un piccolo intoppo qui. Dal momento che potremmo già avere record, dobbiamo assicurarci che abbiano contatori corretti. Puoi farlo dalla console, ma a lungo termine è una buona idea crea un'attività di rake .

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

L'operazione potrebbe richiedere un po' di tempo poiché è necessario estrarre ciascuna opzione e aggiornare il conteggio.

Ora possiamo visualizzare il conteggio in questo modo:

<% 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 è abbastanza intelligente da utilizzare la nostra colonna della cache del contatore, ma tornerà a interrogare il conteggio che è una buona cosa per i test.