Commit 8b923e2a7ac08e4c49372c3f87c0f268f976d25d

Authored by Antonio Terceiro
2 parents dbf574bf e6ab5837

Merge branch 'stable'

app/controllers/public/content_viewer_controller.rb
@@ -78,13 +78,7 @@ class ContentViewerController < ApplicationController @@ -78,13 +78,7 @@ class ContentViewerController < ApplicationController
78 end 78 end
79 79
80 if @page.blog? 80 if @page.blog?
81 - posts = if params[:year] and params[:month]  
82 - filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01")  
83 - @page.posts.by_range(filter_date..Article.last_day_of_month(filter_date))  
84 - else  
85 - @page.posts  
86 - end  
87 - @posts = available_articles(posts, user).paginate :page => params[:npage], :per_page => @page.posts_per_page 81 + @page.filter = {:year => params[:year], :month => params[:month]}
88 end 82 end
89 83
90 if @page.folder? && @page.view_as == 'image_gallery' 84 if @page.folder? && @page.view_as == 'image_gallery'
app/helpers/blog_helper.rb
@@ -14,7 +14,7 @@ module BlogHelper @@ -14,7 +14,7 @@ module BlogHelper
14 _('Edit blog') 14 _('Edit blog')
15 end 15 end
16 16
17 - def list_posts(articles, format = 'full') 17 + def list_posts(user, articles, format = 'full')
18 pagination = will_paginate(articles, { 18 pagination = will_paginate(articles, {
19 :param_name => 'npage', 19 :param_name => 'npage',
20 :prev_label => _('« Newer posts'), 20 :prev_label => _('« Newer posts'),
@@ -25,16 +25,18 @@ module BlogHelper @@ -25,16 +25,18 @@ module BlogHelper
25 articles.each_with_index{ |art,i| 25 articles.each_with_index{ |art,i|
26 css_add = [ 'position-'+(i+1).to_s() ] 26 css_add = [ 'position-'+(i+1).to_s() ]
27 position = (i%2 == 0) ? 'odd-post' : 'even-post' 27 position = (i%2 == 0) ? 'odd-post' : 'even-post'
28 - css_add << 'first' if i == 0  
29 - css_add << 'last' if i == (artic_len-1)  
30 - css_add << 'not-published' if !art.published?  
31 - css_add << position + '-inner'  
32 - content << content_tag('div',  
33 - content_tag('div',  
34 - display_post(art, format) + '<br style="clear:both"/>',  
35 - :class => 'blog-post ' + css_add.join(' '),  
36 - :id => "post-#{art.id}"), :class => position  
37 - ) 28 + if art.published? || (user==art.profile)
  29 + css_add << 'first' if i == 0
  30 + css_add << 'last' if i == (artic_len-1)
  31 + css_add << 'not-published' if !art.published?
  32 + css_add << position + '-inner'
  33 + content << content_tag('div',
  34 + content_tag('div',
  35 + display_post(art, format) + '<br style="clear:both"/>',
  36 + :class => 'blog-post ' + css_add.join(' '),
  37 + :id => "post-#{art.id}"), :class => position
  38 + )
  39 + end
38 } 40 }
39 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '') 41 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
40 end 42 end
app/models/article.rb
@@ -32,23 +32,6 @@ class Article &lt; ActiveRecord::Base @@ -32,23 +32,6 @@ class Article &lt; ActiveRecord::Base
32 {:include => 'categories', :conditions => { 'categories.id' => category.id }} 32 {:include => 'categories', :conditions => { 'categories.id' => category.id }}
33 } 33 }
34 34
35 - named_scope :by_range, lambda { |range| {  
36 - :conditions => [  
37 - 'published_at BETWEEN :start_date AND :end_date', { :start_date => range.first, :end_date => range.last }  
38 - ]  
39 - }}  
40 -  
41 - def self.first_day_of_month(date)  
42 - date ||= Date.today  
43 - Date.new(date.year, date.month, 1)  
44 - end  
45 -  
46 - def self.last_day_of_month(date)  
47 - date ||= Date.today  
48 - date >>= 1  
49 - Date.new(date.year, date.month, 1) - 1.day  
50 - end  
51 -  
52 URL_FORMAT = /\A(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\Z/ix 35 URL_FORMAT = /\A(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\Z/ix
53 36
54 validates_format_of :external_link, :with => URL_FORMAT, :if => lambda { |article| !article.external_link.blank? } 37 validates_format_of :external_link, :with => URL_FORMAT, :if => lambda { |article| !article.external_link.blank? }
app/models/blog.rb
@@ -3,6 +3,7 @@ class Blog &lt; Folder @@ -3,6 +3,7 @@ class Blog &lt; Folder
3 has_many :posts, :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'type != ?', 'RssFeed' ], :order => 'published_at DESC, id DESC' 3 has_many :posts, :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'type != ?', 'RssFeed' ], :order => 'published_at DESC, id DESC'
4 4
5 attr_accessor :feed_attrs 5 attr_accessor :feed_attrs
  6 + attr_accessor :filter
6 7
7 after_create do |blog| 8 after_create do |blog|
8 blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile) 9 blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile)
@@ -22,9 +23,7 @@ class Blog &lt; Folder @@ -22,9 +23,7 @@ class Blog &lt; Folder
22 # FIXME isn't this too much including just to be able to generate some HTML? 23 # FIXME isn't this too much including just to be able to generate some HTML?
23 include ActionView::Helpers::TagHelper 24 include ActionView::Helpers::TagHelper
24 def to_html(options = {}) 25 def to_html(options = {})
25 - lambda do  
26 - render :file => 'content_viewer/blog_page'  
27 - end 26 + posts_list(options[:page])
28 end 27 end
29 28
30 def folder? 29 def folder?
@@ -50,6 +49,19 @@ class Blog &lt; Folder @@ -50,6 +49,19 @@ class Blog &lt; Folder
50 self.feed 49 self.feed
51 end 50 end
52 51
  52 + def posts_list(npage)
  53 + article = self
  54 + children = if filter and filter[:year] and filter[:month]
  55 + filter_date = DateTime.parse("#{filter[:year]}-#{filter[:month]}-01")
  56 + posts.paginate :page => npage, :per_page => posts_per_page, :conditions => [ 'published_at between ? and ?', filter_date, filter_date + 1.month - 1.day ]
  57 + else
  58 + posts.paginate :page => npage, :per_page => posts_per_page
  59 + end
  60 + lambda do
  61 + render :file => 'content_viewer/blog_page', :locals => {:article => article, :children => children}
  62 + end
  63 + end
  64 +
53 has_one :external_feed, :foreign_key => 'blog_id', :dependent => :destroy 65 has_one :external_feed, :foreign_key => 'blog_id', :dependent => :destroy
54 66
55 attr_accessor :external_feed_data 67 attr_accessor :external_feed_data
app/models/event.rb
@@ -56,6 +56,17 @@ class Event &lt; Article @@ -56,6 +56,17 @@ class Event &lt; Article
56 first_day..last_day 56 first_day..last_day
57 end 57 end
58 58
  59 + def self.first_day_of_month(date)
  60 + date ||= Date.today
  61 + Date.new(date.year, date.month, 1)
  62 + end
  63 +
  64 + def self.last_day_of_month(date)
  65 + date ||= Date.today
  66 + date >>= 1
  67 + Date.new(date.year, date.month, 1) - 1.day
  68 + end
  69 +
59 def date_range 70 def date_range
60 start_date..(end_date||start_date) 71 start_date..(end_date||start_date)
61 end 72 end
app/views/content_viewer/blog_page.rhtml
1 -<% add_rss_feed_to_head(@page.name, @page.feed.url) if @page.blog? && @page.feed %> 1 +<% add_rss_feed_to_head(article.name, article.feed.url) if article.blog? && article.feed %>
2 2
3 -<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if @page.blog? && @page.external_feed && @page.external_feed.enabled && @page.external_feed.fetched_at.nil? %> 3 +<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if article.blog? && article.external_feed && article.external_feed.enabled && article.external_feed.fetched_at.nil? %>
4 4
5 <div> 5 <div>
6 - <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.blog? && @page.feed %> 6 + <%= link_to(image_tag('icons-mime/rss-feed.png'), article.feed.url, :class => 'blog-feed-link') if article.blog? && article.feed %>
7 <div class='blog-description'> 7 <div class='blog-description'>
8 - <%= @page.body %> 8 + <%= article.body %>
9 </div> 9 </div>
10 </div> 10 </div>
11 <hr class="pre-posts"/> 11 <hr class="pre-posts"/>
12 <div class="blog-posts"> 12 <div class="blog-posts">
13 - <%= (@posts.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(@posts, @page.visualization_format)) %> 13 + <%= (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(user, children, article.visualization_format)) %>
14 </div> 14 </div>
lib/tasks/test.rake
@@ -20,5 +20,5 @@ end @@ -20,5 +20,5 @@ end
20 20
21 desc 'Runs Seleniun acceptance tests' 21 desc 'Runs Seleniun acceptance tests'
22 task :selenium do 22 task :selenium do
23 - sh "xvfb-run cucumber -p selenium --format #{ENV['CUCUMBER_FORMAT'] || 'progress'}" 23 + sh "xvfb-run -a cucumber -p selenium --format #{ENV['CUCUMBER_FORMAT'] || 'progress'}"
24 end 24 end
test/functional/content_viewer_controller_test.rb
@@ -603,27 +603,10 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -603,27 +603,10 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
603 assert_response :missing 603 assert_response :missing
604 end 604 end
605 605
606 - should 'list unpublished posts to owner with a different class' do  
607 - login_as('testinguser')  
608 - blog = Blog.create!(:name => 'A blog test', :profile => profile)  
609 - blog.posts << TextileArticle.create!(:name => 'Post', :profile => profile, :parent => blog, :published => false)  
610 -  
611 - get :view_page, :profile => profile.identifier, :page => [blog.path]  
612 - assert_tag :tag => 'div', :attributes => {:class => /not-published/}  
613 - end  
614 -  
615 - should 'not list unpublished posts to a not logged person' do  
616 - blog = Blog.create!(:name => 'A blog test', :profile => profile)  
617 - blog.posts << TextileArticle.create!(:name => 'Post', :profile => profile, :parent => blog, :published => false)  
618 -  
619 - get :view_page, :profile => profile.identifier, :page => [blog.path]  
620 - assert_no_tag :tag => 'a', :content => "Post"  
621 - end  
622 -  
623 should 'display pagination links of blog' do 606 should 'display pagination links of blog' do
624 blog = Blog.create!(:name => 'A blog test', :profile => profile, :posts_per_page => 5) 607 blog = Blog.create!(:name => 'A blog test', :profile => profile, :posts_per_page => 5)
625 for n in 1..10 608 for n in 1..10
626 - blog.posts << TextileArticle.create!(:name => "Post #{n}", :profile => profile, :parent => blog) 609 + blog.children << TextileArticle.create!(:name => "Post #{n}", :profile => profile, :parent => blog)
627 end 610 end
628 assert_equal 10, blog.posts.size 611 assert_equal 10, blog.posts.size
629 612
@@ -631,17 +614,11 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -631,17 +614,11 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
631 assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{blog.path}?npage=2", :rel => 'next' } 614 assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{blog.path}?npage=2", :rel => 'next' }
632 end 615 end
633 616
634 - should 'display filtered posts' do  
635 - blog = Blog.create!(:name => 'A blog test', :profile => profile)  
636 - not_display_post = TextileArticle.new(:name => "Post 1", :profile => profile, :parent => blog)  
637 - display_post = TextileArticle.new(:name => "Post 2", :profile => profile, :parent => blog)  
638 -  
639 - not_display_post.update_attribute(:published_at, DateTime.parse('2009-09-10'))  
640 - display_post.update_attribute(:published_at, DateTime.parse('2010-09-10'))  
641 -  
642 - get :view_page, :profile => profile.identifier, :page => [blog.path], :year => 2010, :month => 9  
643 - assert_no_tag :tag => 'a', :content => "Post 1"  
644 - assert_tag :tag => 'a', :content => "Post 2" 617 + should 'set year and month filter from URL params' do
  618 + profile.articles << Blog.new(:name => 'A blog test', :profile => profile)
  619 + year, month = profile.blog.created_at.year.to_s, '%02d' % profile.blog.created_at.month
  620 + get :view_page, :profile => profile.identifier, :page => [profile.blog.path], :year => year, :month => month
  621 + assert_equal({ :year => year.to_s, :month => month.to_s }, assigns(:page).filter)
645 end 622 end
646 623
647 should 'give link to create new article inside folder when view child of folder' do 624 should 'give link to create new article inside folder when view child of folder' do
test/integration/performance_test.rb 0 → 100644
@@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
  1 +require "#{File.dirname(__FILE__)}/../test_helper"
  2 +require 'benchmark'
  3 +
  4 +class PerformanceTest < ActionController::IntegrationTest
  5 +
  6 + all_fixtures
  7 +
  8 + # Testing blog page display. It should not present a linear increase in time
  9 + # needed to display a blog page with the increase in number of posts.
  10 + #
  11 + # GOOD BAD
  12 + #
  13 + # ^ ^ /
  14 + # | | /
  15 + # | _____ | /
  16 + # | / | /
  17 + # | / | /
  18 + # |/ |/
  19 + # +---------> +--------->
  20 + # 0 50 100 0 50 100
  21 + #
  22 + should 'not have a linear increase in time to display a blog page' do
  23 + person = create_profile('clueless')
  24 +
  25 + # no posts
  26 + time0 = (Benchmark.measure { get '/clueless/blog' })
  27 +
  28 + # first 50
  29 + create_posts(person)
  30 + time1 = (Benchmark.measure { get '/clueless/blog' })
  31 +
  32 + # another 50
  33 + create_posts(person)
  34 + time2 = (Benchmark.measure { get '/clueless/blog' })
  35 +
  36 + # should not scale linearly, i.e. the inclination of the first segment must
  37 + # be a lot higher than the one of the segment segment. To compensate for
  38 + # small variations due to hardware and/or execution environment, we are
  39 + # satisfied if the the inclination of the first segment is at least twice
  40 + # the inclination of the second segment.
  41 + a1 = (time1.total - time0.total)/50.0
  42 + a2 = (time2.total - time1.total)/50.0
  43 + assert a1 > a2*2, "#{a1} should be larger than #{a2} by at least a factor of 2"
  44 + end
  45 +
  46 + protected
  47 +
  48 + def create_profile(name)
  49 + person = create_user(name).person
  50 + Blog.create(:name => "Blog", :profile => person)
  51 + person
  52 + end
  53 +
  54 + def create_posts(profile)
  55 + postnumber = profile.articles.count
  56 + blog = profile.blog
  57 + 50.times do |i|
  58 + postnumber += 1
  59 + TinyMceArticle.create!(:profile => profile, :parent => blog, :name => "post number #{postnumber}")
  60 + end
  61 + end
  62 +
  63 +end
  64 +
test/unit/article_test.rb
@@ -873,22 +873,4 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -873,22 +873,4 @@ class ArticleTest &lt; Test::Unit::TestCase
873 assert_no_match /[<>]/, article.name 873 assert_no_match /[<>]/, article.name
874 end 874 end
875 875
876 - should 'found articles with published date between a range' do  
877 - start_date = DateTime.parse('2010-07-06')  
878 - end_date = DateTime.parse('2010-08-02')  
879 -  
880 - article_found1 = fast_create(Article, :published_at => start_date)  
881 - article_found2 = fast_create(Article, :published_at => end_date)  
882 - article_not_found = fast_create(Article, :published_at => end_date + 1.month)  
883 -  
884 - assert_includes Article.by_range(start_date..end_date), article_found1  
885 - assert_includes Article.by_range(start_date..end_date), article_found2  
886 - assert_not_includes Article.by_range(start_date..end_date), article_not_found  
887 - end  
888 -  
889 - should 'calculate first/end day of a month' do  
890 - assert_equal 1, Article.first_day_of_month(DateTime.parse('2010-07-06')).day  
891 - assert_equal 31, Article.last_day_of_month(DateTime.parse('2010-07-06')).day  
892 - end  
893 -  
894 end 876 end
test/unit/blog_helper_test.rb
@@ -27,7 +27,28 @@ class BlogHelperTest &lt; Test::Unit::TestCase @@ -27,7 +27,28 @@ class BlogHelperTest &lt; Test::Unit::TestCase
27 expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last odd-post-inner', :id => "post-#{published_post.id}").returns('POST') 27 expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last odd-post-inner', :id => "post-#{published_post.id}").returns('POST')
28 expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT') 28 expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')
29 29
30 - assert_equal 'RESULT', list_posts(blog.posts) 30 + assert_equal 'RESULT', list_posts(profile, blog.posts)
  31 + end
  32 +
  33 + should 'list unpublished posts to owner with a different class' do
  34 + blog.children << unpublished_post = TextileArticle.create!(:name => 'Post', :profile => profile, :parent => blog, :published => false)
  35 +
  36 + expects(:display_post).with(anything, anything).returns('POST')
  37 + expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last not-published odd-post-inner', :id => "post-#{unpublished_post.id}").returns('POST')
  38 + expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')
  39 + assert_equal 'RESULT', list_posts(profile, blog.posts)
  40 + end
  41 +
  42 + should 'not list unpublished posts to not owner' do
  43 + blog.children << unpublished_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => blog, :published => false)
  44 +
  45 + blog.children << published_post = TextileArticle.create!(:name => 'Second post', :profile => profile, :parent => blog, :published => true)
  46 +
  47 + expects(:display_post).with(anything, anything).returns('POST')
  48 + expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", has_entries(:id => "post-#{unpublished_post.id}")).never
  49 + expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", has_entries(:id => "post-#{published_post.id}")).returns('POST')
  50 + expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')
  51 + assert_equal 'RESULT', list_posts(nil, blog.posts)
31 end 52 end
32 53
33 should 'list even/odd posts with a different class' do 54 should 'list even/odd posts with a different class' do
@@ -43,7 +64,7 @@ class BlogHelperTest &lt; Test::Unit::TestCase @@ -43,7 +64,7 @@ class BlogHelperTest &lt; Test::Unit::TestCase
43 expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-2 last even-post-inner', :id => "post-#{older_post.id}").returns('POST 2') 64 expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-2 last even-post-inner', :id => "post-#{older_post.id}").returns('POST 2')
44 expects(:content_tag).with('div', "POST 2", :class => 'even-post').returns('EVEN-POST') 65 expects(:content_tag).with('div', "POST 2", :class => 'even-post').returns('EVEN-POST')
45 66
46 - assert_equal "ODD-POST\n<hr class='sep-posts'/>\nEVEN-POST", list_posts(blog.posts) 67 + assert_equal "ODD-POST\n<hr class='sep-posts'/>\nEVEN-POST", list_posts(nil, blog.posts)
47 end 68 end
48 69
49 70
test/unit/blog_test.rb
@@ -82,6 +82,13 @@ class BlogTest &lt; ActiveSupport::TestCase @@ -82,6 +82,13 @@ class BlogTest &lt; ActiveSupport::TestCase
82 assert_equal [newer, older], blog.posts 82 assert_equal [newer, older], blog.posts
83 end 83 end
84 84
  85 + should 'has filter' do
  86 + p = create_user('testuser').person
  87 + blog = Blog.create!(:profile => p, :name => 'Blog test')
  88 + blog.filter = {:param => 'value'}
  89 + assert_equal 'value', blog.filter[:param]
  90 + end
  91 +
85 should 'has one external feed' do 92 should 'has one external feed' do
86 p = create_user('testuser').person 93 p = create_user('testuser').person
87 blog = fast_create(Blog, :profile_id => p.id, :name => 'Blog test') 94 blog = fast_create(Blog, :profile_id => p.id, :name => 'Blog test')
test/unit/content_viewer_helper_test.rb
@@ -57,10 +57,32 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase @@ -57,10 +57,32 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
57 should 'not list feed article' do 57 should 'not list feed article' do
58 profile.articles << Blog.new(:name => 'Blog test', :profile => profile) 58 profile.articles << Blog.new(:name => 'Blog test', :profile => profile)
59 assert_includes profile.blog.children.map{|i| i.class}, RssFeed 59 assert_includes profile.blog.children.map{|i| i.class}, RssFeed
60 - result = list_posts(profile.blog.posts) 60 + result = list_posts(nil, profile.blog.posts)
61 assert_no_match /feed/, result 61 assert_no_match /feed/, result
62 end 62 end
63 63
  64 + should 'filter blog posts by date' do
  65 + blog = Blog.create!(:name => 'Blog test', :profile => profile)
  66 +
  67 + nov = TextileArticle.create!(:name => 'November post', :parent => blog, :profile => profile)
  68 + nov.update_attributes!(:published_at => DateTime.parse('2008-11-15'))
  69 +
  70 + sep = TextileArticle.create!(:name => 'September post', :parent => blog, :profile => profile)
  71 + sep.update_attribute(:published_at, DateTime.parse('2008-09-10'))
  72 +
  73 + blog.reload
  74 + blog.filter = {:year => 2008, :month => 11}
  75 + assert blog.save!
  76 +
  77 + self.stubs(:params).returns({:npage => nil})
  78 +
  79 + expects(:render).with(:file => 'content_viewer/blog_page', :locals => {:article => blog, :children => [nov]}).returns("BLI")
  80 +
  81 + result = article_to_html(blog)
  82 +
  83 + assert_equal 'BLI', result
  84 + end
  85 +
64 end 86 end
65 87
66 def show_date(date) 88 def show_date(date)