2015-07-16 2 views
4

У меня есть представление, которое повторяется через ряд сообщений, и подсчитывает количество голосов для каждого. Я знаю, как вообще загружать загрузку и как использовать кэш-счетчики в целом. Но я не могу понять, как использовать счетчик кэша, который поставляется с acts_as_votable (или я делаю что-то еще не так.)Использование количества кеша для act_as_votable

Вид:

 <span class="votes"> 
     <% if current_user.voted_for? link %> 
      <%= link_to like_link_path(link), class: "likes active", id: "link-#{link.id}", remote: true, method: :put do %> 
      <i class="fa fa-heart"></i> <%= link.cached_votes_total.to_s %> 
      <% end %> 
     <% else %> 
      <%= link_to like_link_path(link), class: "likes", id: "link-#{link.id}", remote: true, method: :put do %> 
      <i class="fa fa-heart-o"></i> <%= link.cached_votes_total.to_s %> 
      <% end %> 
     <% end %> 
     </span> 

Terminal:

Link Load (0.4ms) SELECT "links".* FROM "links" ORDER BY "links"."score" DESC LIMIT 10 OFFSET 0 
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (1) 
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] 
(0.2ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."voter_id" = $1 AND "votes"."voter_type" = $2 AND "votes"."votable_id" = $3 AND "votes"."votable_type" = $4 AND "votes"."vote_scope" IS NULL [["voter_id", 1], ["voter_type", "User"], ["votable_id", 1], ["votable_type", "Link"]] 
(0.2ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."voter_id" = $1 AND "votes"."voter_type" = $2 AND "votes"."votable_id" = $3 AND "votes"."votable_type" = $4 AND "votes"."vote_scope" IS NULL [["voter_id", 1], ["voter_type", "User"], ["votable_id", 2], ["votable_type", "Link"]] 
Rendered home/index.html.erb within layouts/application (24.6ms) 
Completed 200 OK in 60ms (Views: 56.9ms | ActiveRecord: 1.6ms) 

Благодаря!

ответ

2

Для меня это выглядело совершенно ненормально. Метод voted_for? является псевдонимом voted_on?. Продолжайте читать код, который вы найдете, этот метод вызывает votes.size > 0, который вызывает следующие запросы к базе данных. (Наверное, у вас есть две ссылки на вашей странице, верно?) Таким образом, это не имеет никакого отношения к полям кешированных счетчиков.

(0.2ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."voter_id" = $1 AND "votes"."voter_type" = $2 AND "votes"."votable_id" = $3 AND "votes"."votable_type" = $4 AND "votes"."vote_scope" IS NULL [["voter_id", 1], ["voter_type", "User"], ["votable_id", 1], ["votable_type", "Link"]] 
(0.2ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."voter_id" = $1 AND "votes"."voter_type" = $2 AND "votes"."votable_id" = $3 AND "votes"."votable_type" = $4 AND "votes"."vote_scope" IS NULL [["voter_id", 1], ["voter_type", "User"], ["votable_id", 2], ["votable_type", "Link"]] 

P.S. Код находится здесь: github: voter.rb.

+0

Да, чтобы избежать каждой ссылки, вызывающей запрос, я хочу знать, какую модель должна включать 'include'. Этот вопрос связан с нетерпением, верно? Вот почему я создаю щедрость для этого вопроса. – ironsand

2

Может быть, это не самый лучший способ, но он может помочь поджать голоса пользователя для ссылок в одном хите базы данных:

  1. Где-то в интерфейсе (например, модель пользователя) вы можете определить метод, как

    # votable - records, which were voted by user, links in the case 
    def preloaded_votes(votable) 
        @preloaded_votes ||= Vote.where(voter: self, votable: votable).group(:votable_id).count 
    end 
    

    этот метод возвращает хэш как {votable_id1 => count1, votable_id2 => count2 }, где votable_idN означает идентификатор элемента из votable аргумента для метода.

  2. Изменить текущий вызов current_user.voted_for? link к предустановленным подсчетам current_user.preloaded_votes.key?(link.id)

Это решение добавляет еще один хит базы данных, но позволяет избежать N+1 запросов. Кроме того, дополнительный SQL не содержит соединений таблиц. Один из возможных способов улучшения здесь - добавить специальный индекс для такого рода запросов.