diff --git a/app/controllers/forem/forums_controller.rb b/app/controllers/forem/forums_controller.rb index 96e392bd6..4237ac953 100644 --- a/app/controllers/forem/forums_controller.rb +++ b/app/controllers/forem/forums_controller.rb @@ -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 diff --git a/app/helpers/forem/topics_helper.rb b/app/helpers/forem/topics_helper.rb index 9356b496d..5f85595db 100644 --- a/app/helpers/forem/topics_helper.rb +++ b/app/helpers/forem/topics_helper.rb @@ -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 diff --git a/app/models/forem/concerns/viewable.rb b/app/models/forem/concerns/viewable.rb index 796c36936..b5875d0dc 100644 --- a/app/models/forem/concerns/viewable.rb +++ b/app/models/forem/concerns/viewable.rb @@ -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 diff --git a/app/models/forem/view.rb b/app/models/forem/view.rb index 69a60dec8..615b99848 100644 --- a/app/models/forem/view.rb +++ b/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 @@ -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 diff --git a/app/views/forem/topics/_topic.html.erb b/app/views/forem/topics/_topic.html.erb index 261044296..cc88ef602 100644 --- a/app/views/forem/topics/_topic.html.erb +++ b/app/views/forem/topics/_topic.html.erb @@ -21,5 +21,5 @@ <%= link_to_latest_post(topic.posts.by_created_at.last) -%> <%= topic.posts.count %> - <%= topic.views.sum(:count) %> + <%= topic.views_count %> diff --git a/db/migrate/20120302152918_add_forem_view_fields.rb b/db/migrate/20120302152918_add_forem_view_fields.rb new file mode 100644 index 000000000..7f7a052fb --- /dev/null +++ b/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 diff --git a/spec/requests/2 b/spec/requests/2 new file mode 100644 index 000000000..9da3efccf --- /dev/null +++ b/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 diff --git a/spec/requests/forums_spec.rb b/spec/requests/forums_spec.rb index 4e0812540..38f0e55a3 100644 --- a/spec/requests/forums_spec.rb +++ b/spec/requests/forums_spec.rb @@ -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