Reputation: 31
I've been unable to retrieve most viewed posts in my app with impressionist gem. Everything works fine with normal page views. I've tried this on another app and it works well. The only difference between the two apps is that the one that that worked uses SQLITE while the other PG.
I've implemented it by installing the gem, i generated the table migration rails g impressionist
and added the impressions_count to posts
rails g migration add_impressions_count_to_posts impressions_count:integer
Added this to Post.rb
is_impressionable :counter_cache => true
and
Post.order('impressions_count DESC')
Added this to posts_controller.rb in show action
@most_viewed = Post.order('impressions_count DESC').take(20)
Below is my post controller code:
class PostsController < ApplicationController
before_action :redirect_if_not_signed_in, only: [:new, :edit, :destroy, :interests_feed]
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :find_category
before_action :find_contacts
before_action :set_actions
impressionist :actions=>[:show,:index]
def show
if user_signed_in?
@message_has_been_sent = conversation_exist?
end
impressionist(@post)
@most_viewed = Post.order('impressions_count DESC').take(10)
end
def new
@branch = params[:branch]
@categories = Category.where(branch: @branch)
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to post_path(@post)
else
redirect_to root_path
end
end
def edit
@categories = Category.all.map{ |c| [c.name, c.id] }
end
def update
if @post.update(post_params)
redirect_to post_path(@post)
else
render 'edit'
end
end
# DELETE /stories/1
# DELETE /stories/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to root_path, notice: 'post was successfully deleted.' }
format.json { head :no_content }
end
end
def hobby
impressionist(@post)
posts_for_branch(params[:action])
end
def study
posts_for_branch(params[:action])
end
def team
posts_for_branch(params[:action])
end
def interests_feed
@my_interests = current_user.tag_ids
@posts = Post.select { |p| (p.tag_ids & @my_interests).any? }
end
def most_viewed
@most_viewed = Post.order('impressions_count DESC').take(20)
@categories = Category.where(branch: @branch)
end
def saved_questions
@saved_questions = current_user.saved_questions
end
private
def conversation_exist?
Private::Conversation.between_users(current_user.id, @post.user.id).present?
end
def post_params
params.require(:post).permit(:content, :title, :category_id, :tag_list, tag_ids: [])
.merge(user_id: current_user.id)
end
def find_post
@post = Post.includes(:tags).find(params[:id])
end
def find_category
@categories = Category.where(branch: @branch)
end
def find_contacts
@contacts = user_signed_in? ? current_user.all_active_contacts : ''
end
def posts_for_branch(branch)
@categories = Category.where(branch: branch)
@posts = get_posts.paginate(page: params[:page])
@most_viewed = Post.order('impressions_count DESC').take(20)
respond_to do |format|
format.html
format.js { render partial: 'posts/posts_pagination_page' }
end
end
def get_posts
PostsForBranchService.new({
search: params[:search],
category: params[:category],
branch: params[:action]
}).call
end
def set_actions
if user_signed_in?
@saved_questions = current_user.saved_questions
end
end
end
and my post model
class Post < ApplicationRecord
belongs_to :user
belongs_to :category
is_impressionable :counter_cache => true
Post.order('impressions_count DESC')
validates :title, presence: true, length: { minimum: 5, maximum: 255 }
validates :content, presence: true, length: { minimum: 20, maximum: 1000 }
validates :category_id, presence: true
default_scope -> { includes(:user).order(created_at: :desc) }
scope :by_category, -> (branch, category_name) do
joins(:category).where(categories: {name: category_name, branch: branch})
end
scope :by_branch, -> (branch) do
joins(:category).where(categories: {branch: branch})
end
scope :search, -> (search) do
where("title ILIKE lower(?) OR content ILIKE lower(?)", "%#{search}%", "%#{search}%")
end
scope :most_recent, -> { order(created_at: :desc) }
has_many :taggings
has_many :tags, through: :taggings
has_many :comments, as: :commentable, dependent: :destroy
has_many :upvotes, dependent: :destroy
has_many :save_questions, dependent: :destroy
def tag_list
self.tags.collect do |tag|
tag.name
end.join(", ")
end
def tag_list=(tags_string)
tag_names = tags_string.split(",").collect{|s| s.strip.downcase}.uniq
new_or_found_tags = tag_names.collect { |name| Tag.friendly.find_or_create_by(name: name) }
self.tags = new_or_found_tags
end
def related_posts
Post.joins(:tags).where(tags: { id: self.tags.pluck(:id) }).where.not(id: self.id)
end
end
show.html.erb
<div id="single-post-content" class="container">
<div class="row">
<div class="col-sm-8 bg-white">
<h1><%= @post.title %></h1>
<hr class="custom-hr">
<% unless @post.tags.blank? %>
<p>
<span>
Tags:
<% @post.tags.each do |tag| %>
<%= link_to tag.name, tag_path(tag), class: "button button_highlight" %>
<% end %>
</span>
</p>
<% end %>
<p>
<span class="text-muted">Asked on <%= @post.created_at.strftime('%-d %B %Y')%> ago by <%= link_to @post.user.name, profile_path(@post.user.name) %> <%= link_to (image_tag @post.user.avatar.url(:comment), class: "img-circle"), profile_path(@post.user.name) %></span> | <span class="text-muted"><%= pluralize(@post.comments.count, "Responses") %></span> | <span class="text-muted"><%= pluralize(@post.impressionist_count, "View") %></span>
<span id="post_<%= @post.id %>_save_questions">
<%= render partial: "save_questions", locals: {post: @post} %>
</span>
</p>
<p id="post_<%= @post.id %>_upvotes">
<%= render partial: "upvotes", locals: {post: @post} %>
</p>
<hr class="custom-hr">
<p><%= sanitize @post.content %></p>
<% if user_signed_in? %>
<% if @post.user_id == current_user.id %>
<span><%= link_to 'Edit Question', edit_post_path(@post), class: "btn btn-warning btn-sm" %></span>
<span><%= link_to 'Delete Question', @post, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger btn-sm" %></span>
<% end %>
<% end %>
<hr class="custom-hr">
<div>
<p><b>Note:</b> This user doesn't know if you're sending this D.M as a response to a question. so your DM could be in this format <i>"As a response to "Are you a male?", Yes, I am.</i></p>
<%= link_to 'Send your response as a private message', open_private_conversation_path(id: @post.user.id), remote: true, method: :post, class: 'bigger-screen-link btn btn-primary btn-sm' %>
<%= link_to 'Send your response as a private message', open_messenger_path(id: @post.user.id, smaller_device: true, type: 'private'), class: 'smaller-screen-link btn btn-primary btn-sm' %>
</div>
<p>Or write a public response below.</p>
<br>
<div>
<%= render "comments/widget", commentable: @post %>
</div>
</div>
<div class="col-sm-4">
<h4>Quick Navigation</h4>
<div class="list-group">
<%= link_to 'My Interests', my_interests_path, class: "list-group-item" %>
<%= link_to 'Trending', trending_path, class: "list-group-item" %>
<a href="#" class="list-group-item">Hot</a>
<%= link_to '20 Most Viewed', most_viewed_path, class: "list-group-item" %>
<a href="#" class="list-group-item">Unanswered</a>
<a href="#" class="list-group-item">From Friends</a>
</div>
<h4>Related Questions</h4>
<hr class="custom-hr">
<% unless @post.related_posts.blank? %>
<ol>
<% @post.related_posts.most_recent.limit(10).reject { |p| p.id == @post.id }.each do |post| %>
<li><%= link_to post.title, post_path(post.id) %></li>
<% end %>
</ol>
<% else %>
<p class="text-warning">This question is not related to others.</p>
<% end %>
<br>
<div class="">
<h4>20 Most Viewed in this Directory.</h4>
<ol>
<% @most_viewed.each do |post| %>
<li><%= link_to post.title, post_path(post.id) %> (<%= post.impressionist_count %> Views) </li>
<% end %>
</ol>
</div>
<br>
<% unless @post.category.blank? %>
<h4>More in Questions <%= link_to @post.category.name, posts_path(branch: @post.category.name) %></h4>
<hr class="custom-hr">
<ol>
<% @post.category.posts.most_recent.limit(11).reject { |p| p.id == @post.id }.each do |post| %>
<li><%= link_to post.title, post_path(post.id) %></li>
<% end %>
</ol>
<% end %>
</div>
</div><!-- row -->
</div>
I have the imprssions table in my schema
create_table "impressions", force: :cascade do |t|
t.string "impressionable_type"
t.integer "impressionable_id"
t.integer "user_id"
t.string "controller_name"
t.string "action_name"
t.string "view_name"
t.string "request_hash"
t.string "ip_address"
t.string "session_hash"
t.text "message"
t.text "referrer"
t.text "params"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["controller_name", "action_name", "ip_address"], name: "controlleraction_ip_index"
t.index ["controller_name", "action_name", "request_hash"], name: "controlleraction_request_index"
t.index ["controller_name", "action_name", "session_hash"], name: "controlleraction_session_index"
t.index ["impressionable_type", "impressionable_id", "ip_address"], name: "poly_ip_index"
t.index ["impressionable_type", "impressionable_id", "params"], name: "poly_params_request_index"
t.index ["impressionable_type", "impressionable_id", "request_hash"], name: "poly_request_index"
t.index ["impressionable_type", "impressionable_id", "session_hash"], name: "poly_session_index"
t.index ["impressionable_type", "message", "impressionable_id"], name: "impressionable_type_message_index"
t.index ["user_id"], name: "index_impressions_on_user_id"
end
Upvotes: 0
Views: 152