Using cache for act_as_votable

I have a view that repeats through a series of posts and counts the number of votes for each. I know how to load a load in general and how to use cache counters in general. But I can't figure out how to use the cache counter that comes with act_as_votable (or am I doing something else wrong).

View:

        <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)

Thank!

+4
source share
2 answers

. voted_for? voted_on?. , , votes.size > 0, . (, 2 , ?) , .

(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.

+2

, , :

  • - (, )

    # 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 id votable .

  • current_user.voted_for? link current_user.preloaded_votes.key?(link.id)

, N+1. , SQL . - .

+2

Source: https://habr.com/ru/post/1598285/