Skip to content

Commit

Permalink
rubysherpas#143 - more detailed forum and topic view tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
jgadbois committed Mar 2, 2012
1 parent cc37db4 commit d33b2c2
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 10 deletions.
1 change: 1 addition & 0 deletions app/controllers/forem/forums_controller.rb
Expand Up @@ -10,6 +10,7 @@ def index
def show
@forum = Forem::Forum.find(params[:id])
register_view

@topics = forem_admin? ? @forum.topics : @forum.topics.visible
@topics = @topics.by_pinned_or_most_recent_post.page(params[:page]).per(20)
end
Expand Down
3 changes: 1 addition & 2 deletions app/helpers/forem/topics_helper.rb
Expand Up @@ -7,12 +7,11 @@ def link_to_latest_post(post)

def new_since_last_view_text(topic)
if forem_user
# hasn't been viewed and was created within 15 minutes of last forum view
topic_view = topic.view_for(forem_user)
forum_view = topic.forum.view_for(forem_user)

if forum_view
if topic_view.nil? && (topic.created_at - forum_view.viewed_at) < 15.minutes
if topic_view.nil? && topic.created_at > forum_view.past_viewed_at
content_tag :super, "New"
end
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/forem/concerns/viewable.rb
Expand Up @@ -18,6 +18,14 @@ def register_view_by(user)
if user
view = views.find_or_create_by_user_id(user.id)
view.increment!("count")
increment!(:views_count)

# update current viewed at if more than 15 minutes ago
if view.current_viewed_at < 15.minutes.ago
view.past_viewed_at = view.current_viewed_at
view.current_viewed_at = Time.now
view.save
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/forem/view.rb
@@ -1,5 +1,7 @@
module Forem
class View < ActiveRecord::Base
before_create :set_viewed_at_to_now

belongs_to :viewable, :polymorphic => true
belongs_to :user, :class_name => Forem.user_class.to_s

Expand All @@ -9,5 +11,11 @@ class View < ActiveRecord::Base
def viewed_at
updated_at
end

private
def set_viewed_at_to_now
self.current_viewed_at = Time.now
self.past_viewed_at = current_viewed_at
end
end
end
2 changes: 1 addition & 1 deletion app/views/forem/topics/_topic.html.erb
Expand Up @@ -21,5 +21,5 @@
<%= link_to_latest_post(topic.posts.by_created_at.last) -%>
</td>
<td class='posts-count'><%= topic.posts.count %></td>
<td class='views-count'><%= topic.views.sum(:count) %></td>
<td class='views-count'><%= topic.views_count %></td>
</tr>
23 changes: 23 additions & 0 deletions db/migrate/20120302152918_add_forem_view_fields.rb
@@ -0,0 +1,23 @@
class AddForemViewFields < ActiveRecord::Migration
def up
add_column :forem_views, :current_viewed_at, :datetime
add_column :forem_views, :past_viewed_at, :datetime
add_column :forem_topics, :views_count, :integer, :default=>0
add_column :forem_forums, :views_count, :integer, :default=>0

Forem::Topic.find_each do |topic|
topic.update_column(:views_count, topics.views.sum(:count))
end

Forem::Forum.find_each do |forum|
forum.update_column(:views_count, forum.topics.sum(:views_count))
end
end

def down
remove_column :forem_views, :current_viewed_at, :datetime
remove_column :forem_views, :past_viewed_at, :datetime
remove_column :forem_topics, :views_count, :integer, :default=>0
remove_column :forem_forums, :views_count, :integer, :default=>0
end
end
71 changes: 71 additions & 0 deletions spec/requests/2
@@ -0,0 +1,71 @@
require 'spec_helper'

describe "forums" do
let!(:forum) { FactoryGirl.create(:forum) }

it "listing all" do
visit forums_path
within(".forum") do
page.should have_content("Welcome to Forem!")
within(".description") do
page.should have_content("A placeholder forum.")
end
end
end

context "visiting a forum" do
before do
@topic_1 = FactoryGirl.create(:topic, :subject => "Unpinned", :forum => forum)
@topic_2 = FactoryGirl.create(:topic, :subject => "Most Recent", :forum => forum)
FactoryGirl.create(:post, :topic => @topic_2, :created_at => Time.now + 30.seconds)
@topic_3 = FactoryGirl.create(:topic, :subject => "PINNED!", :forum => forum, :pinned => true)
@topic_4 = FactoryGirl.create(:topic, :subject => "HIDDEN!", :forum => forum, :hidden => true)
visit forum_path(forum)
end

it "lists pinned topics first" do
# TODO: cleaner way to get at topic subjects on the page?
topic_subjects = Nokogiri::HTML(page.body).css(".topics tbody tr .subject").map(&:text)
topic_subjects.should == ["PINNED!", "Most Recent", "Unpinned"]
end

it "does not show hidden topics" do
# TODO: cleaner way to get at topic subjects on the page?
topic_subjects = Nokogiri::HTML(page.body).css(".topics tbody tr .subject").map(&:text)
topic_subjects.include?("HIDDEN!").should be_false
end

context "when logged in" do
before do
@user = Factory(:user)
sign_in(@user)
end
it "calls out topics that have been posted to since your last visit, if you've visited" do
visit forum_topic_path(forum.id, @topic_2)
::Forem::View.last.update_attribute(:updated_at, 1.minute.ago)
visit forum_path(forum)
topic_subjects = Nokogiri::HTML(page.body).css(".topics tbody tr .new_posts")
topic_subjects.should_not be_empty
end

it "calls out new topics since last visit" do
forum.topics.clear
forum.register_view_by(@user)
forum.view_for(@user).update_attribute(:updated_at, 3.days.ago)

new_topic = FactoryGirl.create(:topic, :subject => "New Since Visit", :forum => forum, :created_at=>1.day.ago)
old_topic = FactoryGirl.create(:topic, :subject => "Already Viewed", :forum => forum, :created_at=>4.day.ago)

visit forum_path(forum)
new_topics = Nokogiri::HTML(page.body).css(".topics tbody tr super")
new_topics.size.should eq(1) # should include the one just created

visit forum_topic_path(forum, topic)

visit forum_path(forum)
new_topics = Nokogiri::HTML(page.body).css(".topics tbody tr super")
new_topics.size.should eq(3) # should include the one just created
end
end
end
end
29 changes: 22 additions & 7 deletions spec/requests/forums_spec.rb
Expand Up @@ -48,14 +48,29 @@
topic_subjects.should_not be_empty
end

it "calls out new topics since last visit" do
forum.register_view_by(@user)
forum.view_for(@user).update_attribute(:updated_at, 3.days.ago)
FactoryGirl.create(:topic, :subject => "New Since Visit", :forum => forum, :created_at=>1.day.ago)
context "checking new topics" do
before do
forum.register_view_by(@user)
forum.view_for(@user).update_attribute(:past_viewed_at, 3.days.ago)
@topic_1.created_at = 1.day.ago
@topic_2.created_at = 1.day.ago
@topic_3.created_at = 1.day.ago
@topic_4.created_at = 4.days.ago
end

visit forum_path(forum)
new_topics = Nokogiri::HTML(page.body).css(".topics tbody tr super")
new_topics.size.should eq(4) # should include the one just created
it "calls out new topics since last visit" do
visit forum_path(forum)
new_topics = Nokogiri::HTML(page.body).css(".topics tbody tr super")
new_topics.size.should eq(3)
end

it "doesn't call out a topic that has been viewed" do
visit forum_path(forum)
visit forum_topic_path(forum, @topic_1)
visit forum_path(forum)
new_topics = Nokogiri::HTML(page.body).css(".topics tbody tr super")
new_topics.size.should eq(2)
end
end
end
end
Expand Down

0 comments on commit d33b2c2

Please sign in to comment.