Commit 1a2f1931f49d544f3d636a8e3df925dc871b73c5

Authored by Joenio Costa
Committed by Antonio Terceiro
1 parent 4a74f898

ActionItem935: external blog repeater

app/helpers/blog_helper.rb
... ... @@ -35,4 +35,5 @@ module BlogHelper
35 35 article_title(article) + content_tag('p', article.to_html) +
36 36 content_tag('p', link_to( number_of_comments(article), article.url.merge(:form => 'opened', :anchor => 'comment_form') ), :class => 'metadata')
37 37 end
  38 +
38 39 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -20,7 +20,7 @@ module ContentViewerHelper
20 20 unless args[:no_link]
21 21 title = content_tag('h3', link_to(article.name, article.url), :class => 'title')
22 22 end
23   - title << content_tag('span', _("%s, by %s") % [show_date(article.created_at), link_to(article.author.name, article.author.url)], :class => 'created-at')
  23 + title << content_tag('span', _("%s, by %s") % [show_date(article.published_at), link_to(article.author.name, article.author.url)], :class => 'created-at')
24 24 end
25 25 title
26 26 end
... ...
app/models/article.rb
... ... @@ -20,6 +20,10 @@ class Article &lt; ActiveRecord::Base
20 20  
21 21 settings_items :display_hits, :type => :boolean, :default => true
22 22  
  23 + before_create do |article|
  24 + article.published_at = article.created_at if article.published_at.nil?
  25 + end
  26 +
23 27 def self.human_attribute_name(attrib)
24 28 case attrib.to_sym
25 29 when :name
... ...
app/models/blog.rb
1 1 class Blog < Folder
2 2  
3   - has_many :posts, :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'type != ?', 'RssFeed' ], :order => 'created_at DESC'
  3 + has_many :posts, :class_name => 'Article', :foreign_key => 'parent_id', :source => :children, :conditions => [ 'type != ?', 'RssFeed' ], :order => 'published_at DESC'
4 4  
5 5 attr_accessor :feed_attrs
6 6 attr_accessor :filter
... ... @@ -56,7 +56,7 @@ class Blog &lt; Folder
56 56 article = self
57 57 children = if filter and filter[:year] and filter[:month]
58 58 filter_date = DateTime.parse("#{filter[:year]}-#{filter[:month]}-01")
59   - posts.paginate :page => npage, :per_page => posts_per_page, :conditions => [ 'created_at between ? and ?', filter_date, filter_date + 1.month - 1.day ]
  59 + posts.paginate :page => npage, :per_page => posts_per_page, :conditions => [ 'published_at between ? and ?', filter_date, filter_date + 1.month - 1.day ]
60 60 else
61 61 posts.paginate :page => npage, :per_page => posts_per_page
62 62 end
... ... @@ -64,4 +64,33 @@ class Blog &lt; Folder
64 64 render :file => 'content_viewer/blog_page', :locals => {:article => article, :children => children}
65 65 end
66 66 end
  67 +
  68 + has_one :external_feed, :foreign_key => 'blog_id'
  69 +
  70 + attr_accessor :external_feed_data
  71 + def external_feed_builder=(efeed)
  72 + self.external_feed_data = efeed
  73 + end
  74 +
  75 + def validate
  76 + unless self.external_feed_data.nil?
  77 + if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i
  78 + self.external_feed.attributes = self.external_feed_data
  79 + else
  80 + self.build_external_feed(self.external_feed_data)
  81 + end
  82 + self.external_feed.valid?
  83 + self.external_feed.errors.delete(:blog_id) # dont validate here relation: external_feed <-> blog
  84 + self.external_feed.errors.each do |attr,msg|
  85 + self.errors.add(attr, msg)
  86 + end
  87 + end
  88 + end
  89 +
  90 + after_save do |blog|
  91 + if blog.external_feed
  92 + blog.external_feed.save
  93 + end
  94 + end
  95 +
67 96 end
... ...
app/models/blog_archives_block.rb
... ... @@ -18,10 +18,10 @@ class BlogArchivesBlock &lt; Block
18 18 return nil unless owner.has_blog?
19 19 results = ''
20 20 posts = owner.blog.posts
21   - posts.group_by{|i| i.created_at.year}.each do |year, results_by_year|
  21 + posts.group_by{|i| i.published_at.year}.each do |year, results_by_year|
22 22 results << content_tag('li', content_tag('strong', "#{year} (#{results_by_year.size})"))
23 23 results << "<ul class='#{year}-archive'>"
24   - results_by_year.group_by{|i| [ ('%02d' % i.created_at.month()), gettext(MONTHS[i.created_at.month() - 1])]}.sort.each do |month, results_by_month|
  24 + results_by_year.group_by{|i| [ ('%02d' % i.published_at.month()), gettext(MONTHS[i.published_at.month() - 1])]}.sort.each do |month, results_by_month|
25 25 results << content_tag('li', link_to("#{month[1]} (#{results_by_month.size})", owner.generate_url(:controller => 'content_viewer', :action => 'view_page', :page => [owner.blog.path, year, month[0]])))
26 26 end
27 27 results << "</ul>"
... ...
app/models/external_feed.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +class ExternalFeed < ActiveRecord::Base
  2 +
  3 + belongs_to :blog
  4 + validates_presence_of :blog_id
  5 + validates_presence_of :address, :if => lambda {|efeed| efeed.enabled}
  6 + validates_uniqueness_of :blog_id
  7 +
  8 + def add_item(title, link, date, content)
  9 + article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog)
  10 + unless blog.children.exists?(:slug => article.slug)
  11 + article.save!
  12 + end
  13 + end
  14 +
  15 + def clear
  16 + # do nothing
  17 + end
  18 + def finish_fetch
  19 + if self.only_once
  20 + self.enabled = 'false'
  21 + end
  22 + self.save!
  23 + end
  24 +
  25 + def limit
  26 + 0
  27 + end
  28 +
  29 +end
... ...
app/models/feed_reader_block.rb
... ... @@ -48,6 +48,9 @@ class FeedReaderBlock &lt; Block
48 48 self.feed_items = []
49 49 self.feed_title = nil
50 50 end
  51 + def finish_fetch
  52 + self.save!
  53 + end
51 54  
52 55 def content
53 56 block_title(title) + formatted_feed_content
... ...
app/views/cms/_blog.rhtml
  1 +<%= error_messages_for 'blog' %>
  2 +
1 3 <h3><%= _('My Blog') %></h3>
2 4  
3 5 <%= render :file => 'shared/tiny_mce' %>
... ... @@ -8,12 +10,26 @@
8 10  
9 11 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, [5, 10, 20, 50, 100])) %>
10 12  
11   -<% fields_for 'article[feed]', @article.feed do |feed| %>
12   -
13   -<%= labelled_form_field(_('Limit of posts in RSS Feed'), feed.select(:limit, ['5', '10', '20', '50'])) %>
14   -
15   -<%= labelled_form_field(_('Use as description in RSS Feed:'), feed.select(:feed_item_description, [ [ _('Article abstract'), 'abstract'], [ _('Article body'), 'body']])) %>
  13 +<% f.fields_for 'feed', @article.feed do |feed| %>
  14 + <%= labelled_form_field(_('Limit of posts in RSS Feed'), feed.select(:limit, ['5', '10', '20', '50'])) %>
  15 + <%= labelled_form_field(_('Use as description in RSS Feed:'), feed.select(:feed_item_description, [ [ _('Article abstract'), 'abstract'], [ _('Article body'), 'body']])) %>
  16 +<% end %>
16 17  
  18 +<% f.fields_for 'external_feed_builder', @article.external_feed do |efeed| %>
  19 + <div id='fetch-external-feed'>
  20 + <% enabled = @article.external_feed && @article.external_feed.enabled %>
  21 + <% only_once = @article.external_feed ? @article.external_feed.only_once : true %>
  22 + <%= labelled_check_box(_('Fetch posts from an external feed'), 'article[external_feed_builder][enabled]', 'true', enabled, {:onchange => "$('external-feed-options').toggle()"}) %>
  23 + <%= hidden_field_tag 'article[external_feed_builder][enabled]', 'false' %>
  24 + <div id='external-feed-options' style="display: <%= enabled ? 'block' : 'none' %>">
  25 + <%= efeed.hidden_field(:id) %>
  26 + <%= labelled_form_field( _('Feed address'), efeed.text_field(:address) ) %>
  27 + <div id='external-feed-options-only-once'>
  28 + <%= labelled_radio_button( _('Fetch posts only once'), 'article[external_feed_builder][only_once]', 'true', only_once) %>
  29 + <%= labelled_radio_button( _('Fetch posts always'), 'article[external_feed_builder][only_once]', 'false', !only_once) %>
  30 + </div>
  31 + </div>
  32 + </div>
17 33 <% end %>
18 34  
19 35 <%= javascript_tag "$('back_to').value = 'control_panel'" %>
... ...
app/views/content_viewer/blog_page.rhtml
  1 +<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if article.blog? && article.external_feed && article.external_feed.fetched_at.nil? %>
  2 +
1 3 <div><%= article.body %></div>
2 4 <hr/>
3 5 <%= (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(user, children)) %>
4   -
5   -
... ...
app/views/content_viewer/view_page.rhtml
... ... @@ -97,6 +97,11 @@
97 97 </div>
98 98 <% end %>
99 99  
  100 +<% if ! @page.source.nil? and ! @page.source.empty?%>
  101 +<div id="article-source">
  102 + <%= _('Source: %s') % link_to(@page.source, @page.source) %>
  103 +</div>
  104 +<% end %>
100 105  
101 106 <div class="comments">
102 107 <% if @page.accept_comments? %>
... ...
db/migrate/063_add_published_at_and_source_to_articles.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class AddPublishedAtAndSourceToArticles < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :articles, :published_at, :date
  4 + add_column :article_versions, :published_at, :date
  5 +
  6 + execute('UPDATE articles SET published_at = created_at WHERE published_at IS NULL')
  7 + execute('UPDATE article_versions SET published_at = created_at WHERE published_at IS NULL')
  8 +
  9 + add_column :articles, :source, :string, :null => true
  10 + add_column :article_versions, :source, :string, :null => true
  11 + end
  12 +
  13 + def self.down
  14 + remove_column :articles, :published_at
  15 + remove_column :article_versions, :published_at
  16 + remove_column :articles, :source
  17 + remove_column :article_versions, :source
  18 + end
  19 +end
... ...
db/migrate/064_create_external_feeds.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class CreateExternalFeeds < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :external_feeds do |t|
  4 + t.string :feed_title
  5 + t.date :fetched_at
  6 + t.string :address
  7 + t.integer :blog_id, :null => false
  8 + t.boolean :enabled, :null => false, :default => true
  9 + t.boolean :only_once, :null => false, :default => true
  10 + t.timestamps
  11 + end
  12 + end
  13 +
  14 + def self.down
  15 + drop_table :external_feeds
  16 + end
  17 +end
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11  
12   -ActiveRecord::Schema.define(:version => 62) do
  12 +ActiveRecord::Schema.define(:version => 64) do
13 13  
14 14 create_table "article_versions", :force => true do |t|
15 15 t.integer "article_id"
... ... @@ -42,6 +42,8 @@ ActiveRecord::Schema.define(:version =&gt; 62) do
42 42 t.text "setting"
43 43 t.boolean "notify_comments", :default => false
44 44 t.integer "hits", :default => 0
  45 + t.date "published_at"
  46 + t.string "source"
45 47 end
46 48  
47 49 create_table "articles", :force => true do |t|
... ... @@ -75,6 +77,8 @@ ActiveRecord::Schema.define(:version =&gt; 62) do
75 77 t.text "setting"
76 78 t.boolean "notify_comments", :default => true
77 79 t.integer "hits", :default => 0
  80 + t.date "published_at"
  81 + t.string "source"
78 82 end
79 83  
80 84 create_table "articles_categories", :id => false, :force => true do |t|
... ... @@ -160,6 +164,17 @@ ActiveRecord::Schema.define(:version =&gt; 62) do
160 164 t.string "theme"
161 165 end
162 166  
  167 + create_table "external_feeds", :force => true do |t|
  168 + t.string "feed_title"
  169 + t.date "fetched_at"
  170 + t.string "address"
  171 + t.integer "blog_id", :null => false
  172 + t.boolean "enabled", :default => true, :null => false
  173 + t.boolean "only_once", :default => true, :null => false
  174 + t.datetime "created_at"
  175 + t.datetime "updated_at"
  176 + end
  177 +
163 178 create_table "favorite_enteprises_people", :id => false, :force => true do |t|
164 179 t.integer "person_id"
165 180 t.integer "enterprise_id"
... ...
lib/feed_handler.rb
... ... @@ -32,7 +32,7 @@ class FeedHandler
32 32 parse.items[0..container.limit-1].each do |item|
33 33 container.add_item(item.title, item.link, item.date, item.content)
34 34 end
35   - container.save!
  35 + container.finish_fetch
36 36 end
37 37 end
38 38  
... ...
public/stylesheets/article.css
... ... @@ -32,6 +32,16 @@
32 32 font-size: 10px;
33 33 }
34 34  
  35 +#article-source {
  36 + color: #999;
  37 + font-size: 11px;
  38 + text-align: right;
  39 + font-weight: bold;
  40 +}
  41 +#article-source a {
  42 + font-weight: normal;
  43 +}
  44 +
35 45 /* * * Comments * * */
36 46  
37 47 .comments { }
... ... @@ -183,12 +193,18 @@
183 193 margin-bottom: 2px;
184 194 }
185 195  
  196 +.metadata,
186 197 .blog-post .metadata {
187 198 display: block;
188 199 text-align: center;
189 200 font-size: small;
190 201 }
191 202  
  203 +.metadata {
  204 + text-align: right;
  205 + color: gray;
  206 +}
  207 +
192 208 #content .created-at {
193 209 color: gray;
194 210 font-size: small;
... ... @@ -237,3 +253,5 @@
237 253 text-align: center;
238 254 font-size: small;
239 255 }
  256 +
  257 +
... ...
public/stylesheets/controller_cms.css
... ... @@ -122,3 +122,26 @@ div.file-manager-button a:hover {
122 122 .file-manager-small .file-manager-controls * {
123 123 text-align: right;
124 124 }
  125 +
  126 +/************* external blog options *****************/
  127 +
  128 +#fetch-external-feed {
  129 + border: 1px solid #EEE;
  130 + padding: 5px;
  131 + margin: 5px 0;
  132 + width: 460px
  133 +}
  134 +#fetch-external-feed label,
  135 +#fetch-external-feed .formfield,
  136 +#fetch-external-feed #external-feed-options #external-feed-options-only-once label,
  137 +#fetch-external-feed #external-feed-options #external-feed-options-only-once .formfieldline,
  138 +#fetch-external-feed #external-feed-options #external-feed-options-only-once .formfield {
  139 + display: inline;
  140 +}
  141 +#fetch-external-feed .type-text input {
  142 + width: 400px;
  143 +}
  144 +#fetch-external-feed #external-feed-options label,
  145 +#fetch-external-feed #external-feed-options .formfield {
  146 + display: block;
  147 +}
... ...
script/feed-updater
1 1 #!/usr/bin/env ruby
2 2 require File.dirname(__FILE__) + '/../config/environment'
3 3  
4   -FeedReaderBlock.find(:all).each do |feed_block|
5   - unless feed_block.address.nil?
  4 +(FeedReaderBlock.find(:all) + ExternalFeed.find(:all, :conditions => {:enabled => true})).each do |container|
  5 + unless container.address.nil?
6 6 begin
7 7 handler = FeedHandler.new
8   - handler.process(feed_block)
9   - RAILS_DEFAULT_LOGGER.info("%s ID %d fetched at %s" % [feed_block.class.name, feed_block.id, feed_block.fetched_at])
  8 + handler.process(container)
  9 + RAILS_DEFAULT_LOGGER.info("%s ID %d fetched at %s" % [container.class.name, container.id, container.fetched_at])
10 10 rescue FeedHandler::ParseError => ex
11   - RAILS_DEFAULT_LOGGER.warn("Error parsing content from %s ID %d\n%s" % [feed_block.class.name, feed_block.id, ex.to_s])
  11 + RAILS_DEFAULT_LOGGER.warn("Error parsing content from %s ID %d\n%s" % [container.class.name, container.id, ex.to_s])
12 12 rescue FeedHandler::FetchError => ex
13   - RAILS_DEFAULT_LOGGER.warn("Error fetching content from %s ID %d\n%s" % [feed_block.class.name, feed_block.id, ex.to_s])
  13 + RAILS_DEFAULT_LOGGER.warn("Error fetching content from %s ID %d\n%s" % [container.class.name, container.id, ex.to_s])
14 14 rescue Exception => ex
15   - RAILS_DEFAULT_LOGGER.warn("Unknown error from %s ID %d\n%s" % [feed_block.class.name, feed_block.id, ex.to_s])
  15 + RAILS_DEFAULT_LOGGER.warn("Unknown error from %s ID %d\n%s" % [container.class.name, container.id, ex.to_s])
16 16 end
17 17 end
18 18 end
... ...
test/functional/cms_controller_test.rb
... ... @@ -716,7 +716,7 @@ class CmsControllerTest &lt; Test::Unit::TestCase
716 716 end
717 717  
718 718 should 'offer to edit a blog' do
719   - profile.articles << Blog.new(:name => 'blog test')
  719 + profile.articles << Blog.new(:name => 'blog test', :profile => profile)
720 720  
721 721 profile.articles.reload
722 722 assert profile.has_blog?
... ... @@ -727,7 +727,7 @@ class CmsControllerTest &lt; Test::Unit::TestCase
727 727 end
728 728  
729 729 should 'not offer to add folder to blog' do
730   - profile.articles << Blog.new(:name => 'blog test')
  730 + profile.articles << Blog.new(:name => 'blog test', :profile => profile)
731 731  
732 732 profile.articles.reload
733 733 assert profile.has_blog?
... ... @@ -737,7 +737,7 @@ class CmsControllerTest &lt; Test::Unit::TestCase
737 737 end
738 738  
739 739 should 'not show feed subitem for blog' do
740   - profile.articles << Blog.new(:name => 'Blog for test')
  740 + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile)
741 741  
742 742 profile.articles.reload
743 743 assert profile.has_blog?
... ... @@ -748,7 +748,7 @@ class CmsControllerTest &lt; Test::Unit::TestCase
748 748 end
749 749  
750 750 should 'update feed options by edit blog form' do
751   - profile.articles << Blog.new(:name => 'Blog for test')
  751 + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile)
752 752 post :edit, :profile => profile.identifier, :id => profile.blog.id, :article => { :feed => { :limit => 7 } }
753 753 assert_equal 7, profile.blog.feed.limit
754 754 end
... ... @@ -770,8 +770,9 @@ class CmsControllerTest &lt; Test::Unit::TestCase
770 770 end
771 771  
772 772 should 'update blog posts_per_page setting' do
773   - profile.articles << Blog.new(:name => 'Blog for test')
  773 + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile)
774 774 post :edit, :profile => profile.identifier, :id => profile.blog.id, :article => { :posts_per_page => 5 }
  775 + profile.blog.reload
775 776 assert_equal 5, profile.blog.posts_per_page
776 777 end
777 778  
... ... @@ -909,4 +910,36 @@ class CmsControllerTest &lt; Test::Unit::TestCase
909 910 assert_template nil
910 911 assert_redirected_to file.url.merge(:view => true)
911 912 end
  913 +
  914 + should 'display external feed options when edit blog' do
  915 + get :new, :profile => profile.identifier, :type => 'Blog'
  916 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][enabled]' }
  917 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][address]' }
  918 + end
  919 +
  920 + should "display 'Fetch posts from an external feed' checked if blog has enabled external feed" do
  921 + profile.articles << Blog.new(:title => 'test blog', :profile => profile)
  922 + profile.blog.create_external_feed(:address => 'address', :enabled => true)
  923 + get :edit, :profile => profile.identifier, :id => profile.blog.id
  924 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][enabled]', :checked => 'checked' }
  925 + end
  926 +
  927 + should "display 'Fetch posts from an external feed' unchecked if blog has disabled external feed" do
  928 + profile.articles << Blog.new(:title => 'test blog', :profile => profile)
  929 + profile.blog.create_external_feed(:address => 'address', :enabled => false)
  930 + get :edit, :profile => profile.identifier, :id => profile.blog.id
  931 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][enabled]', :checked => nil }
  932 + end
  933 +
  934 + should "hide external feed options when 'Fetch posts from an external feed' unchecked" do
  935 + get :new, :profile => profile.identifier, :type => 'Blog'
  936 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][enabled]', :checked => nil }
  937 + assert_tag :tag => 'div', :attributes => { :id => 'external-feed-options', :style => 'display: none' }
  938 + end
  939 +
  940 + should 'only_once option marked by default' do
  941 + get :new, :profile => profile.identifier, :type => 'Blog'
  942 + assert_tag :tag => 'input', :attributes => { :name => 'article[external_feed_builder][only_once]', :checked => 'checked', :value => 'true' }
  943 + end
  944 +
912 945 end
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -14,8 +14,9 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
14 14 @response = ActionController::TestResponse.new
15 15  
16 16 @profile = create_user('testinguser').person
  17 + @environment = @profile.environment
17 18 end
18   - attr_reader :profile
  19 + attr_reader :profile, :environment
19 20  
20 21 def test_local_files_reference
21 22 page = profile.articles.build(:name => 'test')
... ... @@ -638,9 +639,9 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
638 639 end
639 640  
640 641 should 'extract year and month from path' do
641   - blog = Blog.create!(:name => 'A blog test', :profile => profile)
642   - year, month = blog.created_at.year.to_s, '%02d' % blog.created_at.month
643   - get :view_page, :profile => profile.identifier, :page => [blog.path, year, month]
  642 + profile.articles << Blog.new(:name => 'A blog test', :profile => profile)
  643 + year, month = profile.blog.created_at.year.to_s, '%02d' % profile.blog.created_at.month
  644 + get :view_page, :profile => profile.identifier, :page => [profile.blog.path, year, month]
644 645 assert_equal({ :year => year.to_s, :month => month.to_s }, assigns(:page).filter)
645 646 end
646 647  
... ... @@ -693,17 +694,17 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
693 694  
694 695 should 'add meta tag to rss feed on view blog' do
695 696 login_as(profile.identifier)
696   - a = Blog.create!(:name => 'article folder', :profile => profile)
697   - get :view_page, :profile => profile.identifier, :page => [a.path]
698   - assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'feed', :href => /\/#{profile.identifier}\/blog\/feed/}
  697 + profile.articles << Blog.new(:title => 'article blog', :profile => profile)
  698 + get :view_page, :profile => profile.identifier, :page => ['blog']
  699 + assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'feed', :href => "http://#{environment.default_hostname}/testinguser/blog/feed" }
699 700 end
700 701  
701 702 should 'add meta tag to rss feed on view post blog' do
702 703 login_as(profile.identifier)
703   - a = Blog.create!(:name => 'article folder', :profile => profile)
704   - t = TextileArticle.create!(:name => 'first post', :parent => a, :profile => profile)
705   - get :view_page, :profile => profile.identifier, :page => [t.path]
706   - assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'feed', :href => /\/#{profile.identifier}\/blog\/feed/}
  704 + profile.articles << Blog.new(:name => 'article folder', :profile => profile)
  705 + profile.blog.posts << TextileArticle.new(:name => 'first post', :parent => profile.blog, :profile => profile)
  706 + get :view_page, :profile => profile.identifier, :page => ['blog', 'first-post']
  707 + assert_tag :tag => 'link', :attributes => { :rel => 'alternate', :type => 'application/rss+xml', :title => 'feed', :href => "http://#{environment.default_hostname}/testinguser/blog/feed" }
707 708 end
708 709  
709 710 should 'link to post with comment form opened' do
... ... @@ -787,4 +788,16 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
787 788 assert_template 'slideshow'
788 789 end
789 790  
  791 + should 'display source from article' do
  792 + profile.articles << TextileArticle.new(:name => "Article one", :profile => profile, :source => 'http://www.original-source.invalid')
  793 + get :view_page, :profile => profile.identifier, :page => ['article-one']
  794 + assert_tag :tag => 'div', :attributes => { :id => 'article-source' }, :content => /http:\/\/www.original-source.invalid/
  795 + end
  796 +
  797 + should 'not display source if article has no source' do
  798 + profile.articles << TextileArticle.new(:name => "Article one", :profile => profile)
  799 + get :view_page, :profile => profile.identifier, :page => ['article-one']
  800 + assert_no_tag :tag => 'div', :attributes => { :id => 'article-source' }
  801 + end
  802 +
790 803 end
... ...
test/functional/profile_design_controller_test.rb
... ... @@ -274,7 +274,7 @@ class ProfileDesignControllerTest &lt; Test::Unit::TestCase
274 274 end
275 275  
276 276 should 'offer to create blog archives block only if has blog' do
277   - Blog.create!(:name => 'Blog test', :profile => holder)
  277 + holder.articles << Blog.new(:name => 'Blog test', :profile => holder)
278 278 get :add_block, :profile => 'designtestuser'
279 279 assert_tag :tag => 'input', :attributes => { :id => 'type_blogarchivesblock', :value => 'BlogArchivesBlock' }
280 280 end
... ...
test/functional/profile_editor_controller_test.rb
... ... @@ -628,7 +628,7 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
628 628  
629 629 should 'offer to config blog in control panel' do
630 630 profile.articles << Blog.new(:name => 'My blog', :profile => profile)
631   - get :index, :profile => 'default_user'
  631 + get :index, :profile => profile.identifier
632 632 assert_tag :tag => 'a', :attributes => { :href => "/myprofile/default_user/cms/edit/#{profile.blog.id}" }
633 633 end
634 634  
... ...
test/unit/article_test.rb
... ... @@ -684,4 +684,13 @@ class ArticleTest &lt; Test::Unit::TestCase
684 684 assert_equal profile, Article.new(:last_changed_by => nil, :profile => profile).author
685 685 end
686 686  
  687 + should 'have published_at' do
  688 + assert_respond_to Article.new, :published_at
  689 + end
  690 +
  691 + should 'published_at is same as created_at if not set' do
  692 + a = Article.create!(:name => 'Published at', :profile => profile)
  693 + assert_equal a.created_at, a.published_at
  694 + end
  695 +
687 696 end
... ...
test/unit/blog_archives_block_test.rb
... ... @@ -4,7 +4,7 @@ class BlogArchivesBlockTest &lt; ActiveSupport::TestCase
4 4  
5 5 def setup
6 6 @profile = create_user('flatline').person
7   - @profile.articles << Blog.new(:name => 'blog', :profile => @profile)
  7 + @profile.articles << Blog.new(:name => 'blog-test', :profile => @profile)
8 8 end
9 9 attr_reader :profile
10 10  
... ... @@ -22,7 +22,7 @@ class BlogArchivesBlockTest &lt; ActiveSupport::TestCase
22 22 blog = profile.blog
23 23 for i in 1..10 do
24 24 post = TextileArticle.create!(:name => "post #{i} test", :profile => profile, :parent => blog)
25   - post.update_attribute(:created_at, date)
  25 + post.update_attribute(:published_at, date)
26 26 end
27 27 block = BlogArchivesBlock.new
28 28 block.stubs(:owner).returns(profile)
... ... @@ -34,19 +34,18 @@ class BlogArchivesBlockTest &lt; ActiveSupport::TestCase
34 34 blog = profile.blog
35 35 for i in 1..10 do
36 36 post = TextileArticle.create!(:name => "post #{i} test", :profile => profile, :parent => blog)
37   - post.update_attribute(:created_at, date)
  37 + post.update_attribute(:published_at, date)
38 38 end
39 39 block = BlogArchivesBlock.new
40 40 block.stubs(:owner).returns(profile)
41 41 assert_tag_in_string block.content, :tag => 'a', :content => 'January (10)', :attributes => {:href => /2008\/01/}
42 42 end
43 43  
44   -
45 44 should 'order list of amount posts' do
46 45 blog = profile.blog
47 46 for i in 1..10 do
48 47 post = TextileArticle.create!(:name => "post #{i} test", :profile => profile, :parent => blog)
49   - post.update_attribute(:created_at, DateTime.parse("2008-#{i}-01"))
  48 + post.update_attribute(:published_at, DateTime.parse("2008-#{i}-01"))
50 49 end
51 50 block = BlogArchivesBlock.new
52 51 block.stubs(:owner).returns(profile)
... ...
test/unit/blog_test.rb
... ... @@ -38,24 +38,16 @@ class BlogTest &lt; ActiveSupport::TestCase
38 38 assert_equal 'body', b.feed.feed_item_description
39 39 end
40 40  
41   - should 'get first blog from profile' do
42   - p = create_user('testuser').person
43   - b = Blog.create!(:profile => p, :name => 'blog_feed_test')
44   - assert_equal p.blog, b
45   - end
46   -
47 41 should 'save feed options' do
48 42 p = create_user('testuser').person
49   - b = Blog.create!(:profile => p, :name => 'blog_feed_test')
  43 + p.articles << Blog.new(:profile => p, :name => 'blog_feed_test')
50 44 p.blog.feed = { :limit => 7 }
51 45 assert_equal 7, p.blog.feed.limit
52 46 end
53 47  
54 48 should 'save feed options after create blog' do
55 49 p = create_user('testuser').person
56   - b = Blog.create!(:profile => p, :name => 'blog_feed_test', :feed => { :limit => 7 })
57   -
58   - p.blog.feed.reload
  50 + p.articles << Blog.new(:profile => p, :name => 'blog_feed_test', :feed => { :limit => 7 })
59 51 assert_equal 7, p.blog.feed.limit
60 52 end
61 53  
... ... @@ -65,16 +57,16 @@ class BlogTest &lt; ActiveSupport::TestCase
65 57 end
66 58  
67 59 should 'update posts per page setting' do
68   - p = create_user('testusermerda').person
69   - blog = Blog.create!(:profile => p, :name => 'Blog test')
70   - blog.reload
71   - blog.posts_per_page = 5
  60 + p = create_user('testuser').person
  61 + p.articles << Blog.new(:profile => p, :name => 'Blog test')
  62 + blog = p.blog
  63 + blog.posts_per_page = 7
72 64 assert blog.save!
73   - assert_equal 5, blog.posts_per_page
  65 + assert_equal 7, p.blog.posts_per_page
74 66 end
75 67  
76 68 should 'has posts' do
77   - p = create_user('testusermerda').person
  69 + p = create_user('testuser').person
78 70 blog = Blog.create!(:profile => p, :name => 'Blog test')
79 71 post = TextileArticle.create!(:name => 'First post', :profile => p, :parent => blog)
80 72 blog.children << post
... ... @@ -82,25 +74,56 @@ class BlogTest &lt; ActiveSupport::TestCase
82 74 end
83 75  
84 76 should 'not includes rss feed in posts' do
85   - p = create_user('testusermerda').person
  77 + p = create_user('testuser').person
86 78 blog = Blog.create!(:profile => p, :name => 'Blog test')
87 79 assert_includes blog.children, blog.feed
88 80 assert_not_includes blog.posts, blog.feed
89 81 end
90 82  
91   - should 'list posts ordered by created at' do
92   - p = create_user('testusermerda').person
  83 + should 'list posts ordered by published at' do
  84 + p = create_user('testuser').person
93 85 blog = Blog.create!(:profile => p, :name => 'Blog test')
94 86 newer = TextileArticle.create!(:name => 'Post 2', :parent => blog, :profile => p)
95   - older = TextileArticle.create!(:name => 'Post 1', :parent => blog, :profile => p, :created_at => Time.now - 1.month)
  87 + older = TextileArticle.create!(:name => 'Post 1', :parent => blog, :profile => p, :published_at => Time.now - 1.month)
96 88 assert_equal [newer, older], blog.posts
97 89 end
98 90  
99 91 should 'has filter' do
100   - p = create_user('testusermerda').person
  92 + p = create_user('testuser').person
101 93 blog = Blog.create!(:profile => p, :name => 'Blog test')
102 94 blog.filter = {:param => 'value'}
103 95 assert_equal 'value', blog.filter[:param]
104 96 end
105 97  
  98 + should 'has one external feed' do
  99 + p = create_user('testuser').person
  100 + blog = Blog.create!(:profile => p, :name => 'Blog test')
  101 + efeed = blog.create_external_feed(:address => 'http://invalid.url')
  102 + assert_equal efeed, blog.external_feed
  103 + end
  104 +
  105 + should 'build external feed after save' do
  106 + p = create_user('testuser').person
  107 + blog = Blog.new(:profile => p, :name => 'Blog test')
  108 + blog.external_feed_builder = { :address => 'feed address' }
  109 + blog.save!
  110 + assert blog.external_feed.valid?
  111 + end
  112 +
  113 + should 'update external feed' do
  114 + p = create_user('testuser').person
  115 + blog = Blog.new(:profile => p, :name => 'Blog test')
  116 + blog.create_external_feed(:address => 'feed address')
  117 + blog.external_feed_builder = { :address => 'address edited' }
  118 + blog.save!
  119 + assert_equal 'address edited', blog.external_feed.address
  120 + end
  121 +
  122 + should 'invalid blog if has invalid external_feed' do
  123 + p = create_user('testuser').person
  124 + blog = Blog.new(:profile => p, :name => 'Blog test', :external_feed_builder => {:enabled => true})
  125 + blog.save
  126 + assert ! blog.valid?
  127 + end
  128 +
106 129 end
... ...
test/unit/content_viewer_helper_test.rb
... ... @@ -11,17 +11,17 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
11 11 end
12 12 attr :profile
13 13  
14   - should 'display created-at for blog posts' do
  14 + should 'display published-at for blog posts' do
15 15 blog = Blog.create!(:name => 'Blog test', :profile => profile)
16 16 post = TextileArticle.create!(:name => 'post test', :profile => profile, :parent => blog)
17 17 result = article_title(post)
18   - assert_match /#{show_date(post.created_at)}, by .*#{profile.identifier}/, result
  18 + assert_match /#{show_date(post.published_at)}, by .*#{profile.identifier}/, result
19 19 end
20 20  
21   - should 'not display created-at for non-blog posts' do
  21 + should 'not display published-at for non-blog posts' do
22 22 article = TextileArticle.create!(:name => 'article for test', :profile => profile)
23 23 result = article_title(article)
24   - assert_no_match /#{show_date(article.created_at)}, by .*#{profile.identifier}/, result
  24 + assert_no_match /#{show_date(article.published_at)}, by .*#{profile.identifier}/, result
25 25 end
26 26  
27 27 should 'create link on title of blog posts' do
... ... @@ -54,7 +54,7 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
54 54 end
55 55  
56 56 should 'not list feed article' do
57   - profile.articles << Blog.new(:name => 'Blog test')
  57 + profile.articles << Blog.new(:name => 'Blog test', :profile => profile)
58 58 assert_includes profile.blog.children.map{|i| i.class}, RssFeed
59 59 result = list_posts(nil, profile.blog.posts)
60 60 assert_no_match /feed/, result
... ... @@ -64,10 +64,10 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
64 64 blog = Blog.create!(:name => 'Blog test', :profile => profile)
65 65  
66 66 nov = TextileArticle.create!(:name => 'November post', :parent => blog, :profile => profile)
67   - nov.update_attributes!(:created_at => DateTime.parse('2008-11-15'))
  67 + nov.update_attributes!(:published_at => DateTime.parse('2008-11-15'))
68 68  
69 69 sep = TextileArticle.create!(:name => 'September post', :parent => blog, :profile => profile)
70   - sep.update_attribute(:created_at, DateTime.parse('2008-09-10'))
  70 + sep.update_attribute(:published_at, DateTime.parse('2008-09-10'))
71 71  
72 72 blog.reload
73 73 blog.filter = {:year => 2008, :month => 11}
... ...
test/unit/external_feed_test.rb 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ExternalFeedTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @profile = create_user('test-person').person
  7 + @blog = Blog.create!(:name => 'test-blog', :profile => @profile)
  8 + end
  9 + attr_reader :profile, :blog
  10 +
  11 + should 'require blog' do
  12 + e = ExternalFeed.new(:address => 'http://localhost')
  13 + assert !e.valid?
  14 + e.blog = blog
  15 + assert e.save!
  16 + end
  17 +
  18 + should 'belongs to blog' do
  19 + e = ExternalFeed.create!(:address => 'http://localhost', :blog => blog)
  20 + e.reload
  21 + assert_equal blog, e.blog
  22 + end
  23 +
  24 + should 'not add same item twice' do
  25 + e = ExternalFeed.create!(:address => 'http://localhost', :blog => blog)
  26 + assert e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post')
  27 + assert !e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post')
  28 + assert_equal 1, e.blog.posts.size
  29 + end
  30 +
  31 + should 'nothing when clear' do
  32 + assert_respond_to ExternalFeed.new, :clear
  33 + end
  34 +
  35 + should 'not limit' do
  36 + assert_equal 0, ExternalFeed.new.limit
  37 + end
  38 +
  39 + should 'disable external feed if fetch only once on finish fetch' do
  40 + e = ExternalFeed.create(:address => 'http://localhost', :blog => blog, :only_once => true, :enabled => true)
  41 + assert e.enabled
  42 + assert e.finish_fetch
  43 + assert !e.enabled
  44 + end
  45 +
  46 + should 'add items to blog as posts' do
  47 + handler = FeedHandler.new
  48 + e = ExternalFeed.create!(:address => 'test/fixtures/files/feed.xml', :blog => blog, :enabled => true)
  49 + handler.process(e)
  50 + assert_equal ["Last POST", "Second POST", "First POST"], e.blog.posts.map{|i| i.title}
  51 + end
  52 +
  53 + should 'require address if enabled' do
  54 + e = ExternalFeed.new(:blog => blog, :enabled => true)
  55 + assert !e.valid?
  56 + end
  57 +
  58 + should 'not require address if disabled' do
  59 + e = ExternalFeed.new(:blog => blog, :enabled => false)
  60 + assert e.valid?
  61 + end
  62 +
  63 +end
... ...
test/unit/feed_handler_test.rb
... ... @@ -68,8 +68,8 @@ class FeedHandlerTest &lt; Test::Unit::TestCase
68 68 handler.process(container)
69 69 end
70 70  
71   - should 'save after processing' do
72   - container.expects(:save!)
  71 + should 'finish_fetch after processing' do
  72 + container.expects(:finish_fetch)
73 73 handler.process(container)
74 74 end
75 75  
... ...
test/unit/feed_reader_block_test.rb
... ... @@ -68,4 +68,9 @@ class FeedReaderBlockTest &lt; ActiveSupport::TestCase
68 68 assert_equal [], feed.feed_items
69 69 end
70 70  
  71 + should 'save! when commit' do
  72 + feed.expects(:save!)
  73 + feed.finish_fetch
  74 + end
  75 +
71 76 end
... ...
test/unit/profile_test.rb
... ... @@ -1160,7 +1160,7 @@ class ProfileTest &lt; Test::Unit::TestCase
1160 1160  
1161 1161 should 'has blog' do
1162 1162 p = create_user('testuser').person
1163   - b = Blog.create!(:profile => p, :name => 'blog_feed_test')
  1163 + p.articles << Blog.new(:profile => p, :name => 'blog_feed_test')
1164 1164 assert p.has_blog?
1165 1165 end
1166 1166  
... ... @@ -1169,12 +1169,6 @@ class ProfileTest &lt; Test::Unit::TestCase
1169 1169 assert !p.has_blog?
1170 1170 end
1171 1171  
1172   - should 'get blog when has blog' do
1173   - p = create_user('testuser').person
1174   - b = Blog.create!(:profile => p, :name => 'blog_feed_test')
1175   - assert_equal b, p.blog
1176   - end
1177   -
1178 1172 should 'get nil when no blog' do
1179 1173 p = create_user('testuser').person
1180 1174 assert_nil p.blog
... ...
test/unit/published_article_test.rb
... ... @@ -56,10 +56,10 @@ class PublishedArticleTest &lt; ActiveSupport::TestCase
56 56 @article.expects(:parent).returns(parent)
57 57 parent.expects(:blog?).returns(true)
58 58 prof = Community.create!(:name => 'test_comm', :identifier => 'test_comm')
59   - blog = Blog.create!(:profile => prof, :name => 'Blog test')
  59 + prof.articles << Blog.new(:profile => prof, :name => 'Blog test')
60 60 p = PublishedArticle.create!(:reference_article => @article, :profile => prof)
61 61  
62   - assert_equal p.parent, blog
  62 + assert_equal p.parent, prof.blog
63 63 end
64 64  
65 65 should 'not be created in community blog if did not come from a blog' do
... ...
test/unit/rss_feed_test.rb
... ... @@ -109,7 +109,7 @@ class RssFeedTest &lt; Test::Unit::TestCase
109 109  
110 110 should 'list blog posts with more recent first and respecting limit' do
111 111 profile = create_user('testuser').person
112   - blog = Blog.create(:name => 'blog', :profile => profile)
  112 + blog = Blog.create!(:name => 'blog-test', :profile => profile)
113 113 posts = []
114 114 6.times do |i|
115 115 posts << TextArticle.create!(:name => "post #{i}", :profile => profile, :parent => blog)
... ... @@ -123,7 +123,7 @@ class RssFeedTest &lt; Test::Unit::TestCase
123 123  
124 124 should 'list only published posts from blog' do
125 125 profile = create_user('testuser').person
126   - blog = Blog.create(:name => 'blog', :profile => profile)
  126 + blog = Blog.create!(:name => 'blog-test', :profile => profile)
127 127 posts = []
128 128 5.times do |i|
129 129 posts << TextArticle.create!(:name => "post #{i}", :profile => profile, :parent => blog)
... ...
vendor/plugins/active_record_validations_delete/init.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +# monkey patch to remove a single error from the errors collection
  2 +# http://dev.rubyonrails.org/ticket/8137
  3 +
  4 +ActiveRecord::Errors.module_eval do
  5 + # remove a single error from the errors collection by key
  6 + def delete(key)
  7 + @errors.delete(key.to_s)
  8 + end
  9 +end
... ...