Commit 4bbfef7e42eff51025675d1e6f70aee7c26527ff

Authored by Rodrigo Souto
1 parent 457c9f59

article: author refactoring

I'm adding the author as a record relation instead of calculating it
based on the last_changed_by. This change has a reasonable performance
improvement on pages that access this information, like blog page.

Still saving author_name in order to deal with the problem of the author
being removed.

Including new method to facilitate specific article version retrieval.

ActionItem3201
app/controllers/my_profile/cms_controller.rb
@@ -144,6 +144,7 @@ class CmsController < MyProfileController @@ -144,6 +144,7 @@ class CmsController < MyProfileController
144 end 144 end
145 145
146 @article.profile = profile 146 @article.profile = profile
  147 + @article.author = user
147 @article.last_changed_by = user 148 @article.last_changed_by = user
148 149
149 translations if @article.translatable? 150 translations if @article.translatable?
app/controllers/public/content_viewer_controller.rb
@@ -83,7 +83,7 @@ class ContentViewerController < ApplicationController @@ -83,7 +83,7 @@ class ContentViewerController < ApplicationController
83 @page.posts 83 @page.posts
84 end 84 end
85 85
86 - posts = posts.includes(:parent, {:profile => [:domains, :environment]}) 86 + posts = posts.includes(:parent, {:profile => [:domains, :environment]}, :author)
87 87
88 #FIXME Need to run this before the pagination because this version of 88 #FIXME Need to run this before the pagination because this version of
89 # will_paginate returns a will_paginate collection instead of a 89 # will_paginate returns a will_paginate collection instead of a
app/helpers/content_viewer_helper.rb
@@ -26,7 +26,7 @@ module ContentViewerHelper @@ -26,7 +26,7 @@ module ContentViewerHelper
26 end 26 end
27 title << content_tag('span', 27 title << content_tag('span',
28 content_tag('span', show_date(article.published_at), :class => 'date') + 28 content_tag('span', show_date(article.published_at), :class => 'date') +
29 - content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + 29 + content_tag('span', [_(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name)], :class => 'author') +
30 content_tag('span', comments, :class => 'comments'), 30 content_tag('span', comments, :class => 'comments'),
31 :class => 'created-at' 31 :class => 'created-at'
32 ) 32 )
app/models/article.rb
@@ -39,8 +39,8 @@ class Article &lt; ActiveRecord::Base @@ -39,8 +39,8 @@ class Article &lt; ActiveRecord::Base
39 before_save :sanitize_tag_list 39 before_save :sanitize_tag_list
40 40
41 before_create do |article| 41 before_create do |article|
42 - if article.last_changed_by_id  
43 - article.author_name = Person.find(article.last_changed_by_id).name 42 + if article.author
  43 + article.author_name = article.author.name
44 end 44 end
45 end 45 end
46 46
@@ -52,6 +52,7 @@ class Article &lt; ActiveRecord::Base @@ -52,6 +52,7 @@ class Article &lt; ActiveRecord::Base
52 52
53 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } 53 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
54 54
  55 + belongs_to :author, :class_name => 'Person'
55 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 56 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
56 57
57 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' 58 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
@@ -449,7 +450,7 @@ class Article &lt; ActiveRecord::Base @@ -449,7 +450,7 @@ class Article &lt; ActiveRecord::Base
449 ['TextArticle', 'TextileArticle', 'TinyMceArticle'] 450 ['TextArticle', 'TextileArticle', 'TinyMceArticle']
450 end 451 end
451 452
452 - named_scope :published, :conditions => { :published => true } 453 + named_scope :published, :conditions => ['articles.published = ?', true]
453 named_scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }} 454 named_scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }}
454 named_scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} 455 named_scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}}
455 named_scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] 456 named_scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ]
@@ -462,7 +463,7 @@ class Article &lt; ActiveRecord::Base @@ -462,7 +463,7 @@ class Article &lt; ActiveRecord::Base
462 named_scope :more_recent, :order => "created_at DESC" 463 named_scope :more_recent, :order => "created_at DESC"
463 464
464 def self.display_filter(user, profile) 465 def self.display_filter(user, profile)
465 - return {:conditions => ['published = ?', true]} if !user 466 + return {:conditions => ['articles.published = ?', true]} if !user
466 {:conditions => [" articles.published = ? OR 467 {:conditions => [" articles.published = ? OR
467 articles.last_changed_by_id = ? OR 468 articles.last_changed_by_id = ? OR
468 articles.profile_id = ? OR 469 articles.profile_id = ? OR
@@ -621,39 +622,36 @@ class Article &lt; ActiveRecord::Base @@ -621,39 +622,36 @@ class Article &lt; ActiveRecord::Base
621 can_display_versions? && display_versions 622 can_display_versions? && display_versions
622 end 623 end
623 624
624 - def author(version_number = nil)  
625 - if version_number  
626 - version = versions.find_by_version(version_number)  
627 - author_id = version.last_changed_by_id if version  
628 - Person.exists?(author_id) ? Person.find(author_id) : nil  
629 - else  
630 - if versions.empty?  
631 - last_changed_by  
632 - else  
633 - author_id = versions.first.last_changed_by_id  
634 - Person.exists?(author_id) ? Person.find(author_id) : nil  
635 - end  
636 - end 625 + def get_version(version_number = nil)
  626 + version_number ? versions.find(:first, :order => 'version', :offset => version_number - 1) : versions.earliest
  627 + end
  628 +
  629 + def author_by_version(version_number = nil)
  630 + version_number ? profile.environment.people.find_by_id(get_version(version_number).last_changed_by_id) : author
637 end 631 end
638 632
639 def author_name(version_number = nil) 633 def author_name(version_number = nil)
640 - person = author(version_number)  
641 - person ? person.name : (setting[:author_name] || _('Unknown')) 634 + person = author_by_version(version_number)
  635 + if version_number
  636 + person ? person.name : _('Unknown')
  637 + else
  638 + person ? person.name : (setting[:author_name] || _('Unknown'))
  639 + end
642 end 640 end
643 641
644 def author_url(version_number = nil) 642 def author_url(version_number = nil)
645 - person = author(version_number) 643 + person = author_by_version(version_number)
646 person ? person.url : nil 644 person ? person.url : nil
647 end 645 end
648 646
649 def author_id(version_number = nil) 647 def author_id(version_number = nil)
650 - person = author(version_number) 648 + person = author_by_version(version_number)
651 person ? person.id : nil 649 person ? person.id : nil
652 end 650 end
653 651
654 def version_license(version_number = nil) 652 def version_license(version_number = nil)
655 return license if version_number.nil? 653 return license if version_number.nil?
656 - profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) 654 + profile.environment.licenses.find_by_id(get_version(version_number).license_id)
657 end 655 end
658 656
659 alias :active_record_cache_key :cache_key 657 alias :active_record_cache_key :cache_key
db/migrate/20140709224246_create_real_relation_between_article_and_author.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class CreateRealRelationBetweenArticleAndAuthor < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :articles, :author_id, :integer
  4 + add_column :article_versions, :author_id, :integer
  5 +
  6 + # Set article's author as the first version's last_changed_by_id.
  7 + execute "update articles set author_id = (select article_versions.last_changed_by_id from article_versions where article_versions.article_id = articles.id and article_versions.version = 1 limit 1)"
  8 + end
  9 +
  10 + def self.down
  11 + remove_column :articles, :author_id
  12 + remove_column :article_versions, :author_id
  13 + end
  14 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20140709212646) do 12 +ActiveRecord::Schema.define(:version => 20140709224246) do
13 13
14 create_table "abuse_reports", :force => true do |t| 14 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 15 t.integer "reporter_id"
@@ -94,6 +94,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140709212646) do @@ -94,6 +94,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140709212646) do
94 t.integer "image_id" 94 t.integer "image_id"
95 t.integer "position" 95 t.integer "position"
96 t.integer "spam_comments_count", :default => 0 96 t.integer "spam_comments_count", :default => 0
  97 + t.integer "author_id"
97 end 98 end
98 99
99 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" 100 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id"
@@ -140,6 +141,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140709212646) do @@ -140,6 +141,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140709212646) do
140 t.integer "image_id" 141 t.integer "image_id"
141 t.integer "position" 142 t.integer "position"
142 t.integer "spam_comments_count", :default => 0 143 t.integer "spam_comments_count", :default => 0
  144 + t.integer "author_id"
143 end 145 end
144 146
145 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count" 147 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
test/functional/content_viewer_controller_test.rb
@@ -767,7 +767,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -767,7 +767,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
767 c = Community.create!(:name => 'test_com') 767 c = Community.create!(:name => 'test_com')
768 u = create_user_with_permission('test_user', 'publish_content', c) 768 u = create_user_with_permission('test_user', 'publish_content', c)
769 login_as u.identifier 769 login_as u.identifier
770 - a = c.articles.create!(:name => 'test-article', :last_changed_by => u, :published => false) 770 + a = c.articles.create!(:name => 'test-article', :author => u, :published => false)
771 771
772 get :view_page, :profile => c.identifier, :page => a.explode_path 772 get :view_page, :profile => c.identifier, :page => a.explode_path
773 773
@@ -779,7 +779,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -779,7 +779,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
779 c = Community.create!(:name => 'test_com') 779 c = Community.create!(:name => 'test_com')
780 u = create_user_with_permission('test_user', 'publish_content', c) 780 u = create_user_with_permission('test_user', 'publish_content', c)
781 login_as u.identifier 781 login_as u.identifier
782 - a = c.articles.create!(:name => 'test-article', :last_changed_by => profile, :published => true) 782 + a = c.articles.create!(:name => 'test-article', :author => profile, :published => true)
783 783
784 xhr :get, :view_page, :profile => c.identifier, :page => a.explode_path, :toolbar => true 784 xhr :get, :view_page, :profile => c.identifier, :page => a.explode_path, :toolbar => true
785 785
@@ -926,7 +926,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -926,7 +926,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
926 community.add_member(author) 926 community.add_member(author)
927 927
928 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test') 928 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test')
929 - post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :last_changed_by_id => author.id) 929 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :author_id => author.id)
930 930
931 login_as(author.identifier) 931 login_as(author.identifier)
932 get :view_page, :profile => community.identifier, :page => post.path.split('/') 932 get :view_page, :profile => community.identifier, :page => post.path.split('/')
@@ -942,7 +942,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -942,7 +942,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
942 community.add_member(author) 942 community.add_member(author)
943 943
944 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test') 944 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test')
945 - post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :last_changed_by_id => author.id) 945 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :author_id => author.id)
946 946
947 login_as(author.identifier) 947 login_as(author.identifier)
948 get :view_page, :profile => community.identifier, :page => post.path.split('/') 948 get :view_page, :profile => community.identifier, :page => post.path.split('/')
test/unit/article_test.rb
@@ -802,7 +802,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -802,7 +802,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
802 should 'allow author to edit if is publisher' do 802 should 'allow author to edit if is publisher' do
803 c = fast_create(Community) 803 c = fast_create(Community)
804 p = create_user_with_permission('test_user', 'publish_content', c) 804 p = create_user_with_permission('test_user', 'publish_content', c)
805 - a = c.articles.create!(:name => 'a test article', :last_changed_by => p) 805 + a = c.articles.create!(:name => 'a test article', :author => p)
806 806
807 assert a.allow_post_content?(p) 807 assert a.allow_post_content?(p)
808 end 808 end
@@ -1378,7 +1378,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1378,7 +1378,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1378 1378
1379 should "the author_name returns the name of the article's author" do 1379 should "the author_name returns the name of the article's author" do
1380 author = fast_create(Person) 1380 author = fast_create(Person)
1381 - a = profile.articles.create!(:name => 'a test article', :last_changed_by => author) 1381 + a = profile.articles.create!(:name => 'a test article', :author => author)
1382 assert_equal author.name, a.author_name 1382 assert_equal author.name, a.author_name
1383 author.destroy 1383 author.destroy
1384 a.reload 1384 a.reload
@@ -1388,7 +1388,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1388,7 +1388,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1388 1388
1389 should 'retrieve latest info from topic when has no comments' do 1389 should 'retrieve latest info from topic when has no comments' do
1390 forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id) 1390 forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id)
1391 - post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now, :last_changed_by_id => profile.id) 1391 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now, :author_id => profile.id)
1392 assert_equal post.updated_at, post.info_from_last_update[:date] 1392 assert_equal post.updated_at, post.info_from_last_update[:date]
1393 assert_equal profile.name, post.info_from_last_update[:author_name] 1393 assert_equal profile.name, post.info_from_last_update[:author_name]
1394 assert_equal profile.url, post.info_from_last_update[:author_url] 1394 assert_equal profile.url, post.info_from_last_update[:author_url]
@@ -1668,7 +1668,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1668,7 +1668,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1668 author = fast_create(Person) 1668 author = fast_create(Person)
1669 community.add_member(author) 1669 community.add_member(author)
1670 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test') 1670 forum = Forum.create(:profile => community, :name => 'Forum test', :body => 'Forum test')
1671 - post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :last_changed_by_id => author.id) 1671 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => community.id, :parent_id => forum.id, :author_id => author.id)
1672 1672
1673 assert post.allow_edit?(author) 1673 assert post.allow_edit?(author)
1674 end 1674 end
@@ -1753,7 +1753,7 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1753,7 +1753,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1753 1753
1754 should 'set author_name before creating article if there is an author' do 1754 should 'set author_name before creating article if there is an author' do
1755 author = fast_create(Person) 1755 author = fast_create(Person)
1756 - article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => author) 1756 + article = Article.create!(:name => 'Test', :profile => profile, :author => author)
1757 assert_equal author.name, article.author_name 1757 assert_equal author.name, article.author_name
1758 1758
1759 author_name = author.name 1759 author_name = author.name
@@ -1764,12 +1764,12 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1764,12 +1764,12 @@ class ArticleTest &lt; ActiveSupport::TestCase
1764 1764
1765 should "author_id return the author id of the article's author" do 1765 should "author_id return the author id of the article's author" do
1766 author = fast_create(Person) 1766 author = fast_create(Person)
1767 - article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => author) 1767 + article = Article.create!(:name => 'Test', :profile => profile, :author => author)
1768 assert_equal author.id, article.author_id 1768 assert_equal author.id, article.author_id
1769 end 1769 end
1770 1770
1771 should "author_id return nil if there is no article's author" do 1771 should "author_id return nil if there is no article's author" do
1772 - article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => nil) 1772 + article = Article.create!(:name => 'Test', :profile => profile, :author => nil)
1773 assert_nil article.author_id 1773 assert_nil article.author_id
1774 end 1774 end
1775 1775
@@ -1780,8 +1780,8 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1780,8 +1780,8 @@ class ArticleTest &lt; ActiveSupport::TestCase
1780 article.name = 'second version' 1780 article.name = 'second version'
1781 article.last_changed_by = author2 1781 article.last_changed_by = author2
1782 article.save 1782 article.save
1783 - assert_equal author1, article.author(1)  
1784 - assert_equal author2, article.author(2) 1783 + assert_equal author1, article.author_by_version(1)
  1784 + assert_equal author2, article.author_by_version(2)
1785 end 1785 end
1786 1786
1787 should "return the author_name of a specific version" do 1787 should "return the author_name of a specific version" do
@@ -1837,4 +1837,33 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1837,4 +1837,33 @@ class ArticleTest &lt; ActiveSupport::TestCase
1837 assert_equivalent [c3], Article.with_types(['Event']) 1837 assert_equivalent [c3], Article.with_types(['Event'])
1838 end 1838 end
1839 1839
  1840 + should 'get specific version' do
  1841 + article = Article.create!(:name => 'first version', :profile => profile)
  1842 + article.name = 'second version'
  1843 + article.save!
  1844 + article.name = 'third version'
  1845 + article.save!
  1846 +
  1847 + assert_equal 'first version', article.get_version(1).name
  1848 + assert_equal 'second version', article.get_version(2).name
  1849 + assert_equal 'third version', article.get_version(3).name
  1850 + end
  1851 +
  1852 + should 'get author by version' do
  1853 + p1 = fast_create(Person)
  1854 + p2 = fast_create(Person)
  1855 + p3 = fast_create(Person)
  1856 + article = Article.create!(:name => 'first version', :profile => profile, :last_changed_by => p1)
  1857 + article.name = 'second version'
  1858 + article.last_changed_by = p2
  1859 + article.save!
  1860 + article.last_changed_by = p3
  1861 + article.name = 'third version'
  1862 + article.save!
  1863 +
  1864 + assert_equal p1, article.author_by_version(1)
  1865 + assert_equal p2, article.author_by_version(2)
  1866 + assert_equal p3, article.author_by_version(3)
  1867 + end
  1868 +
1840 end 1869 end