Commit a0ef4f259127426b96f8a8ba2bbb2c18c67bf980

Authored by Victor Costa
2 parents 5c4d0723 a1ec80fb

Merge branch 'fix_lazy_queries' into stable

Conflicts:
	app/controllers/public/content_viewer_controller.rb
@@ -24,6 +24,10 @@ gem 'locale', '~> 2.0.5' @@ -24,6 +24,10 @@ gem 'locale', '~> 2.0.5'
24 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 24 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
25 # with their GEM names (not the Debian package names) 25 # with their GEM names (not the Debian package names)
26 26
  27 +group :development do
  28 + gem 'bullet'
  29 +end
  30 +
27 group :production do 31 group :production do
28 gem 'dalli', '~> 2.7.0' 32 gem 'dalli', '~> 2.7.0'
29 end 33 end
app/controllers/my_profile/cms_controller.rb
@@ -59,7 +59,7 @@ class CmsController < MyProfileController @@ -59,7 +59,7 @@ class CmsController < MyProfileController
59 conditions = ['type != ?', 'RssFeed'] 59 conditions = ['type != ?', 'RssFeed']
60 end 60 end
61 61
62 - @articles = @article.children.reorder("case when type = 'Folder' then 0 when type ='Blog' then 1 else 2 end, updated_at DESC, name").paginate( 62 + @articles = @article.children.includes(:parent).reorder("case when type = 'Folder' then 0 when type ='Blog' then 1 else 2 end, updated_at DESC, name").paginate(
63 :conditions => conditions, 63 :conditions => conditions,
64 :per_page => per_page, 64 :per_page => per_page,
65 :page => params[:npage] 65 :page => params[:npage]
app/controllers/public/content_viewer_controller.rb
@@ -8,49 +8,32 @@ class ContentViewerController < ApplicationController @@ -8,49 +8,32 @@ class ContentViewerController < ApplicationController
8 helper TagsHelper 8 helper TagsHelper
9 9
10 def view_page 10 def view_page
11 - path = params[:page]  
12 - path = path.join('/') if path.kind_of?(Array)  
13 - path = "#{path}.#{params[:format]}" if params[:format] 11 + path = get_path(params[:page], params[:format])
  12 +
14 @version = params[:version].to_i 13 @version = params[:version].to_i
15 14
16 if path.blank? 15 if path.blank?
17 - @page = profile.home_page  
18 - if @page.nil?  
19 - redirect_to :controller => 'profile', :action => 'index', :profile => profile.identifier  
20 - return  
21 - end 16 + @page = profile.home_page
  17 + return if redirected_to_profile_index
22 else 18 else
23 @page = profile.articles.find_by_path(path) 19 @page = profile.articles.find_by_path(path)
24 - unless @page  
25 - page_from_old_path = profile.articles.find_by_old_path(path)  
26 - if page_from_old_path  
27 - redirect_to profile.url.merge(:page => page_from_old_path.explode_path)  
28 - return  
29 - end  
30 - end 20 + return if redirected_page_from_old_path(path)
31 end 21 end
32 22
33 return unless allow_access_to_page(path) 23 return unless allow_access_to_page(path)
34 24
35 if @version > 0 25 if @version > 0
36 return render_access_denied unless @page.display_versions? 26 return render_access_denied unless @page.display_versions?
37 - @versioned_article = @page.versions.find_by_version(@version)  
38 - if @versioned_article && @page.versions.latest.version != @versioned_article.version  
39 - render :template => 'content_viewer/versioned_article.html.erb'  
40 - return  
41 - end 27 + return if rendered_versioned_article
42 end 28 end
43 29
44 redirect_to_translation and return if @page.profile.redirect_l10n 30 redirect_to_translation and return if @page.profile.redirect_l10n
45 31
46 - if request.post?  
47 - if @page.forum? && @page.has_terms_of_use && params[:terms_accepted] == "true"  
48 - @page.add_agreed_user(user)  
49 - end  
50 - elsif !@page.parent.nil? && @page.parent.forum?  
51 - unless @page.parent.agrees_with_terms?(user)  
52 - redirect_to @page.parent.url  
53 - end 32 + if request.post? && @page.forum?
  33 + process_forum_terms_of_use(user, params[:terms_accepted])
  34 + elsif is_a_forum_topic?(@page) && !@page.parent.agrees_with_terms?(user)
  35 + redirect_to @page.parent.url
  36 + return
54 end 37 end
55 38
56 # At this point the page will be showed 39 # At this point the page will be showed
@@ -58,64 +41,22 @@ class ContentViewerController < ApplicationController @@ -58,64 +41,22 @@ class ContentViewerController < ApplicationController
58 41
59 @page = FilePresenter.for @page 42 @page = FilePresenter.for @page
60 43
61 - if @page.download? params[:view]  
62 - headers['Content-Type'] = @page.mime_type  
63 - headers.merge! @page.download_headers  
64 - data = @page.data  
65 -  
66 - # TODO test the condition  
67 - if data.nil?  
68 - raise "No data for file"  
69 - end  
70 -  
71 - render :text => data, :layout => false  
72 - return  
73 - end 44 + return if rendered_file_download(params[:view])
74 45
75 @form_div = params[:form] 46 @form_div = params[:form]
76 47
77 #FIXME see a better way to do this. It's not need to pass this variable anymore 48 #FIXME see a better way to do this. It's not need to pass this variable anymore
78 @comment = Comment.new 49 @comment = Comment.new
79 50
80 - if @page.has_posts?  
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..filter_date.at_end_of_month)  
84 - else  
85 - @page.posts  
86 - end  
87 -  
88 - #FIXME Need to run this before the pagination because this version of  
89 - # will_paginate returns a will_paginate collection instead of a  
90 - # relation.  
91 - blog_with_translation = @page.blog? && @page.display_posts_in_current_language?  
92 - posts = posts.native_translations if blog_with_translation  
93 -  
94 - @posts = posts.paginate({ :page => params[:npage], :per_page => @page.posts_per_page }.merge(Article.display_filter(user, profile))).to_a  
95 -  
96 - if blog_with_translation  
97 - @posts.replace @posts.map{ |p| p.get_translation_to(FastGettext.locale) }.compact  
98 - end  
99 - end 51 + process_page_posts(params)
100 52
101 if @page.folder? && @page.gallery? 53 if @page.folder? && @page.gallery?
102 - @images = @page.images.select{ |a| a.display_to? user }  
103 - @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow] 54 + @images = get_images(@page, params[:npage], params[:slideshow])
104 end 55 end
105 56
106 - @unfollow_form = params[:unfollow] && params[:unfollow] == 'true'  
107 - if params[:unfollow] && params[:unfollow] == 'commit' && request.post?  
108 - @page.followers -= [params[:email]]  
109 - if @page.save  
110 - session[:notice] = _("Notification of new comments to '%s' was successfully canceled") % params[:email]  
111 - end  
112 - end 57 + process_page_followers(params)
113 58
114 - @comments = @page.comments.without_spam  
115 - @comments = @plugins.filter(:unavailable_comments, @comments)  
116 - @comments_count = @comments.count  
117 - @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )  
118 - @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order] 59 + process_comments(params)
119 60
120 if request.xhr? and params[:comment_order] 61 if request.xhr? and params[:comment_order]
121 if @comment_order == 'newest' 62 if @comment_order == 'newest'
@@ -129,11 +70,11 @@ class ContentViewerController < ApplicationController @@ -129,11 +70,11 @@ class ContentViewerController < ApplicationController
129 render :action => 'slideshow', :layout => 'slideshow' 70 render :action => 'slideshow', :layout => 'slideshow'
130 return 71 return
131 end 72 end
132 - render @page.view_page, :formats => [:html] 73 + render :view_page, :formats => [:html]
133 end 74 end
134 75
135 def versions_diff 76 def versions_diff
136 - path = params[:page].join('/') 77 + path = params[:page]
137 @page = profile.articles.find_by_path(path) 78 @page = profile.articles.find_by_path(path)
138 @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) 79 @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2])
139 end 80 end
@@ -203,4 +144,127 @@ class ContentViewerController < ApplicationController @@ -203,4 +144,127 @@ class ContentViewerController < ApplicationController
203 user_agent.match(/crawler/) || 144 user_agent.match(/crawler/) ||
204 user_agent.match(/\(.*https?:\/\/.*\)/) 145 user_agent.match(/\(.*https?:\/\/.*\)/)
205 end 146 end
  147 +
  148 + def get_path(page, format = nil)
  149 + path = page
  150 + path = path.join('/') if path.kind_of?(Array)
  151 + path = "#{path}.#{format}" if format
  152 +
  153 + return path
  154 + end
  155 +
  156 + def redirected_to_profile_index
  157 + if @page.nil?
  158 + redirect_to :controller => 'profile', :action => 'index', :profile => profile.identifier
  159 + return true
  160 + end
  161 +
  162 + return false
  163 + end
  164 +
  165 + def redirected_page_from_old_path(path)
  166 + unless @page
  167 + page_from_old_path = profile.articles.find_by_old_path(path)
  168 + if page_from_old_path
  169 + redirect_to profile.url.merge(:page => page_from_old_path.explode_path)
  170 + return true
  171 + end
  172 + end
  173 +
  174 + return false
  175 + end
  176 +
  177 + def process_forum_terms_of_use(user, terms_accepted = nil)
  178 + if @page.forum? && @page.has_terms_of_use && terms_accepted == "true"
  179 + @page.add_agreed_user(user)
  180 + end
  181 + end
  182 +
  183 + def is_a_forum_topic? (page)
  184 + return (!@page.parent.nil? && @page.parent.forum?)
  185 + end
  186 +
  187 + def rendered_versioned_article
  188 + @versioned_article = @page.versions.find_by_version(@version)
  189 + if @versioned_article && @page.versions.latest.version != @versioned_article.version
  190 + render :template => 'content_viewer/versioned_article.html.erb'
  191 + return true
  192 + end
  193 +
  194 + return false
  195 + end
  196 +
  197 + def rendered_file_download(view = nil)
  198 + if @page.download? view
  199 + headers['Content-Type'] = @page.mime_type
  200 + headers.merge! @page.download_headers
  201 + data = @page.data
  202 +
  203 + # TODO test the condition
  204 + if data.nil?
  205 + raise "No data for file"
  206 + end
  207 +
  208 + render :text => data, :layout => false
  209 + return true
  210 + end
  211 +
  212 + return false
  213 + end
  214 +
  215 + def process_page_posts(params)
  216 + if @page.has_posts?
  217 + posts = get_posts(params[:year], params[:month])
  218 +
  219 + #FIXME Need to run this before the pagination because this version of
  220 + # will_paginate returns a will_paginate collection instead of a
  221 + # relation.
  222 + posts = posts.native_translations if blog_with_translation?(@page)
  223 +
  224 + @posts = posts.paginate({ :page => params[:npage], :per_page => @page.posts_per_page }.merge(Article.display_filter(user, profile))).includes(:author).to_a
  225 +
  226 + if blog_with_translation?(@page)
  227 + @posts.replace @posts.map{ |p| p.get_translation_to(FastGettext.locale) }.compact
  228 + end
  229 + end
  230 + end
  231 +
  232 + def get_posts(year = nil, month = nil)
  233 + if year && month
  234 + filter_date = DateTime.parse("#{year}-#{month}-01")
  235 + return @page.posts.by_range(filter_date..filter_date.at_end_of_month)
  236 + else
  237 + return @page.posts
  238 + end
  239 + end
  240 +
  241 + def blog_with_translation?(page)
  242 + return (page.blog? && page.display_posts_in_current_language?)
  243 + end
  244 +
  245 + def get_images(page, npage, slideshow)
  246 + images = page.images.select{ |a| a.display_to? user }
  247 + images = images.paginate(:per_page => per_page, :page => npage) unless slideshow
  248 +
  249 + return images
  250 + end
  251 +
  252 + def process_page_followers(params)
  253 + @unfollow_form = params[:unfollow] == 'true'
  254 + if params[:unfollow] == 'commit' && request.post?
  255 + @page.followers -= [params[:email]]
  256 + if @page.save
  257 + session[:notice] = _("Notification of new comments to '%s' was successfully canceled") % params[:email]
  258 + end
  259 + end
  260 + end
  261 +
  262 + def process_comments(params)
  263 + @comments = @page.comments.without_spam.includes(:source)
  264 + @comments = @plugins.filter(:unavailable_comments, @comments)
  265 + @comments_count = @comments.count
  266 + @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )
  267 + @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
  268 + end
  269 +
206 end 270 end
app/models/article.rb
@@ -58,10 +58,10 @@ class Article < ActiveRecord::Base @@ -58,10 +58,10 @@ class Article < ActiveRecord::Base
58 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 58 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
59 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' 59 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id'
60 60
61 - has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' 61 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'comments.created_at asc', :include => [:author, :children]
62 62
63 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ] 63 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ]
64 - has_many :categories, :through => :article_categorizations 64 + has_many :categories, :through => :article_categorizations, :include => [:environment]
65 65
66 has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization' 66 has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization'
67 has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category 67 has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category
@@ -251,7 +251,7 @@ class Article < ActiveRecord::Base @@ -251,7 +251,7 @@ class Article < ActiveRecord::Base
251 # retrieves all articles belonging to the given +profile+ that are not 251 # retrieves all articles belonging to the given +profile+ that are not
252 # sub-articles of any other article. 252 # sub-articles of any other article.
253 scope :top_level_for, lambda { |profile| 253 scope :top_level_for, lambda { |profile|
254 - {:conditions => [ 'parent_id is null and profile_id = ?', profile.id ]} 254 + {:conditions => [ 'parent_id is null and profile_id = ?', profile.id ], :include => [:profile]}
255 } 255 }
256 256
257 scope :public, 257 scope :public,
@@ -475,7 +475,7 @@ class Article < ActiveRecord::Base @@ -475,7 +475,7 @@ class Article < ActiveRecord::Base
475 end 475 end
476 476
477 scope :published, :conditions => ['articles.published = ?', true] 477 scope :published, :conditions => ['articles.published = ?', true]
478 - scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }} 478 + scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types], :include => [:parent] }}
479 scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} 479 scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}}
480 scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] 480 scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ]
481 scope :images, :conditions => { :is_image => true } 481 scope :images, :conditions => { :is_image => true }
@@ -484,7 +484,7 @@ class Article < ActiveRecord::Base @@ -484,7 +484,7 @@ class Article < ActiveRecord::Base
484 484
485 scope :more_popular, :order => 'hits DESC' 485 scope :more_popular, :order => 'hits DESC'
486 scope :more_comments, :order => "comments_count DESC" 486 scope :more_comments, :order => "comments_count DESC"
487 - scope :more_recent, :order => "created_at DESC" 487 + scope :more_recent, :order => "articles.created_at DESC"
488 488
489 def self.display_filter(user, profile) 489 def self.display_filter(user, profile)
490 return {:conditions => ['articles.published = ?', true]} if !user 490 return {:conditions => ['articles.published = ?', true]} if !user
app/models/category.rb
@@ -16,7 +16,7 @@ class Category < ActiveRecord::Base @@ -16,7 +16,7 @@ class Category < ActiveRecord::Base
16 16
17 # Finds all top level categories for a given environment. 17 # Finds all top level categories for a given environment.
18 scope :top_level_for, lambda { |environment| 18 scope :top_level_for, lambda { |environment|
19 - {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} 19 + {:conditions => ['parent_id is null and environment_id = ?', environment.id ], :include => [:children]}
20 } 20 }
21 21
22 scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} } 22 scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} }
app/models/comment.rb
@@ -18,7 +18,7 @@ class Comment < ActiveRecord::Base @@ -18,7 +18,7 @@ class Comment < ActiveRecord::Base
18 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy 18 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
19 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' 19 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id'
20 20
21 - scope :without_reply, :conditions => ['reply_of_id IS NULL'] 21 + scope :without_reply, :conditions => ['comments.reply_of_id IS NULL']
22 22
23 #FIXME make this test 23 #FIXME make this test
24 scope :newer_than, lambda { |reference_id| 24 scope :newer_than, lambda { |reference_id|
app/models/person.rb
@@ -434,7 +434,7 @@ class Person < Profile @@ -434,7 +434,7 @@ class Person < Profile
434 end 434 end
435 435
436 def already_reported?(profile) 436 def already_reported?(profile)
437 - abuse_reports.any? { |report| report.abuse_complaint.reported == profile && report.abuse_complaint.opened? } 437 + abuse_reports.includes({:abuse_complaint => :reported}).any? { |report| report.abuse_complaint.reported == profile && report.abuse_complaint.opened? }
438 end 438 end
439 439
440 def register_report(abuse_report, profile) 440 def register_report(abuse_report, profile)
app/models/profile.rb
@@ -228,7 +228,7 @@ class Profile < ActiveRecord::Base @@ -228,7 +228,7 @@ class Profile < ActiveRecord::Base
228 belongs_to :preferred_domain, :class_name => 'Domain', :foreign_key => 'preferred_domain_id' 228 belongs_to :preferred_domain, :class_name => 'Domain', :foreign_key => 'preferred_domain_id'
229 belongs_to :environment 229 belongs_to :environment
230 230
231 - has_many :articles, :dependent => :destroy 231 + has_many :articles, :dependent => :destroy, :include => [:profile]
232 belongs_to :home_page, :class_name => Article.name, :foreign_key => 'home_page_id' 232 belongs_to :home_page, :class_name => Article.name, :foreign_key => 'home_page_id'
233 233
234 has_many :files, :class_name => 'UploadedFile' 234 has_many :files, :class_name => 'UploadedFile'
config/environments/development.rb
@@ -35,4 +35,10 @@ Noosfero::Application.configure do @@ -35,4 +35,10 @@ Noosfero::Application.configure do
35 config.assets.debug = true 35 config.assets.debug = true
36 36
37 config.consider_all_requests_local = true 37 config.consider_all_requests_local = true
  38 +
  39 + config.after_initialize do
  40 + Bullet.enable = true
  41 + Bullet.console = true
  42 + end
  43 +
38 end 44 end
lib/acts_as_having_posts.rb
@@ -2,7 +2,7 @@ module ActsAsHavingPosts @@ -2,7 +2,7 @@ module ActsAsHavingPosts
2 2
3 module ClassMethods 3 module ClassMethods
4 def acts_as_having_posts(options = {}) 4 def acts_as_having_posts(options = {})
5 - has_many :posts, { :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'articles.type != ?', 'RssFeed' ], :order => 'published_at DESC, id DESC' }.merge(options) 5 + has_many :posts, { :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'articles.type != ?', 'RssFeed' ], :order => 'published_at DESC, id DESC', :include => [:parent, :profile] }.merge(options)
6 6
7 attr_accessor :feed_attrs 7 attr_accessor :feed_attrs
8 8
lib/spammable.rb
@@ -12,8 +12,8 @@ module Spammable @@ -12,8 +12,8 @@ module Spammable
12 def self.extended (base) 12 def self.extended (base)
13 if base.respond_to?(:scope) 13 if base.respond_to?(:scope)
14 base.class_eval do 14 base.class_eval do
15 - scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false]  
16 - scope :spam, :conditions => ['spam = ?', true] 15 + scope :without_spam, :conditions => ["#{base.table_name}.spam IS NULL OR #{base.table_name}.spam = ?", false]
  16 + scope :spam, :conditions => ["#{base.table_name}.spam = ?", true]
17 end 17 end
18 end 18 end
19 end 19 end