bcms_blog 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/Gemfile +10 -0
  2. data/README.markdown +10 -4
  3. data/app/assets/javascripts/bcms_blog/application.js +15 -0
  4. data/app/assets/stylesheets/bcms_blog/application.css +13 -0
  5. data/app/controllers/bcms_blog/blog_comments_controller.rb +5 -0
  6. data/app/controllers/bcms_blog/blog_posts_controller.rb +37 -0
  7. data/app/controllers/bcms_blog/blogs_controller.rb +13 -0
  8. data/app/controllers/bcms_blog/feeds_controller.rb +10 -0
  9. data/app/helpers/bcms_blog/blog_helper.rb +27 -0
  10. data/app/models/bcms_blog/blog.rb +99 -0
  11. data/app/models/bcms_blog/blog_comment.rb +36 -0
  12. data/app/models/bcms_blog/blog_group_membership.rb +6 -0
  13. data/app/models/bcms_blog/blog_observer.rb +141 -0
  14. data/app/models/bcms_blog/blog_post.rb +108 -0
  15. data/app/portlets/blog_post_portlet.rb +6 -6
  16. data/app/portlets/blog_posts_portlet.rb +4 -4
  17. data/app/views/bcms_blog/blog_comments/_form.html.erb +5 -0
  18. data/app/views/bcms_blog/blog_comments/render.html.erb +2 -0
  19. data/app/views/{cms → bcms_blog}/blog_posts/_form.html.erb +1 -1
  20. data/app/views/{cms → bcms_blog}/blog_posts/no_access.html.erb +0 -0
  21. data/app/views/{cms → bcms_blog}/blog_posts/render.html.erb +0 -0
  22. data/app/views/{cms → bcms_blog}/blogs/_form.html.erb +2 -2
  23. data/app/views/{cms → bcms_blog}/blogs/admin_only.html.erb +0 -0
  24. data/app/views/{cms → bcms_blog}/blogs/render.html.erb +0 -0
  25. data/app/views/{feeds → bcms_blog/feeds}/index.rss.builder +3 -3
  26. data/app/views/portlets/blog_post/_form.html.erb +1 -1
  27. data/app/views/portlets/blog_post/render.html.erb +3 -1
  28. data/app/views/portlets/blog_posts/_form.html.erb +1 -1
  29. data/config/routes.rb +5 -0
  30. data/db/bcms_blog.seeds.rb +4 -0
  31. data/db/migrate/20090415000000_create_blogs.rb +5 -6
  32. data/db/migrate/20090415000001_create_blog_posts.rb +1 -5
  33. data/db/migrate/20090415000002_create_blog_comments.rb +0 -2
  34. data/db/migrate/20120529184028_v130.rb +12 -0
  35. data/lib/bcms_blog/engine.rb +15 -1
  36. data/lib/bcms_blog/route_extensions.rb +8 -0
  37. data/lib/bcms_blog/version.rb +3 -0
  38. data/lib/bcms_blog.rb +5 -2
  39. data/lib/generators/bcms_blog/install/install_generator.rb +11 -11
  40. data/lib/tasks/bcms_blog_tasks.rake +4 -0
  41. data/test/bcms_blog_test.rb +7 -0
  42. data/test/functional/cms/blog_posts_controller_test.rb +47 -0
  43. data/test/functional/cms/blogs_controller_test.rb +27 -0
  44. data/test/integration/blog_controller_test.rb +63 -0
  45. data/test/integration/blog_post_test.rb +31 -0
  46. data/test/support/blog_test_helper.rb +71 -0
  47. data/test/support/factories.rb +54 -0
  48. data/test/support/factory_girl_support.rb +2 -0
  49. data/test/test_helper.rb +15 -0
  50. data/test/test_logging.rb +64 -0
  51. data/test/unit/blog_comment_test.rb +34 -0
  52. data/test/unit/blog_observer_test.rb +84 -0
  53. data/test/unit/blog_post_test.rb +45 -0
  54. data/test/unit/blog_test.rb +42 -0
  55. data/test/unit/helpers/feeds_helper_test.rb +4 -0
  56. metadata +83 -35
  57. data/app/controllers/cms/blog_comments_controller.rb +0 -3
  58. data/app/controllers/cms/blog_posts_controller.rb +0 -35
  59. data/app/controllers/cms/blogs_controller.rb +0 -11
  60. data/app/controllers/feeds_controller.rb +0 -8
  61. data/app/helpers/cms/blog_helper.rb +0 -20
  62. data/app/models/blog.rb +0 -95
  63. data/app/models/blog_comment.rb +0 -34
  64. data/app/models/blog_group_membership.rb +0 -4
  65. data/app/models/blog_observer.rb +0 -140
  66. data/app/models/blog_post.rb +0 -113
  67. data/app/views/cms/blog_comments/_form.html.erb +0 -5
  68. data/app/views/cms/blog_comments/render.html.erb +0 -2
  69. data/app/views/layouts/templates/default.html.erb +0 -17
  70. data/doc/README_FOR_APP +0 -2
  71. data/doc/migrate_to_20100427.rb +0 -77
  72. data/doc/release_notes.txt +0 -48
  73. data/lib/bcms_blog/routes.rb +0 -10
@@ -1,140 +0,0 @@
1
- class BlogObserver < ActiveRecord::Observer
2
-
3
- def after_create(blog)
4
- @blog = blog
5
- create_section_pages_and_routes
6
- end
7
-
8
- def after_save(blog)
9
- if blog.persisted?
10
- blog.publish
11
- end
12
- end
13
-
14
- # Can't use before_update since CMS callback stack is altered from normal callbacks.
15
- def before_save(blog)
16
- if blog.persisted?
17
- update_section_pages_and_route(blog)
18
- end
19
- end
20
-
21
- private
22
-
23
- # A section, two pages, 6 routes and a portlet are created alongside every blog.
24
- # This structure provides sensible defaults so users can pretty much start adding
25
- # posts right after creating a blog without having to worry about where to put
26
- # their blog and portlets.
27
- def create_section_pages_and_routes
28
- create_blog_section
29
- create_blog_block_page
30
- create_post_portlet_page
31
- reload_routes
32
- end
33
-
34
- # Every blog is created within a section with the same name.
35
- # For example, if you create a blog named 'MyBlog', a section 'MyBlog' will be
36
- # created. This section will hold two pages: one for the blog ContentBlock that
37
- # will render the list of posts and one for the BlogPost portlet (ie the individual
38
- # post view)
39
- def create_blog_section
40
- @section = Section.find_by_name(@blog.name) || (
41
- @section = Section.create!(
42
- :name => @blog.name,
43
- :path => "/#{@blog.name_for_path}",
44
- :parent_id => 1
45
- )
46
- @section.allow_groups = :all
47
- @section.save!
48
- @section
49
- )
50
- end
51
-
52
- # Following with the above example, the first page that is created is named 'MyBlog' and
53
- # holds the Blog ContentBlock directly, not a portlet. Together with the 5 created routes,
54
- # this page and its ContentBlock handle different post listings (all posts, posts in year,
55
- # month or day and posts by tag or category).
56
- def create_blog_block_page
57
- page = Page.find_by_name(@blog.name) || Page.create!(
58
- :name => @blog.name,
59
- :path => "/#{@blog.name_for_path}",
60
- :section => @section,
61
- :template_file_name => "default.html.erb",
62
- :hidden => true
63
- )
64
- page.create_connector(@blog, 'main')
65
-
66
- create_route(page, "#{@blog.name}: Posts In Day", "/#{@blog.name_for_path}/:year/:month/:day")
67
- create_route(page, "#{@blog.name}: Posts In Month", "/#{@blog.name_for_path}/:year/:month")
68
- create_route(page, "#{@blog.name}: Posts In Year", "/#{@blog.name_for_path}/:year")
69
- create_route(page, "#{@blog.name}: Posts With Tag", "/#{@blog.name_for_path}/tag/:tag")
70
- create_route(page, "#{@blog.name}: Posts In Category", "/#{@blog.name_for_path}/category/:category")
71
- end
72
-
73
- # The second page that is created holds the BlogPostPortlet and displays the individual
74
- # post view, along with it's comments.
75
- def create_post_portlet_page
76
- page = Page.find_by_name(portlet_name = "#{@blog.name}: Post") || Page.create!(
77
- :name => portlet_name,
78
- :path => "/#{@blog.name_for_path}/post",
79
- :section => @section,
80
- :template_file_name => "default.html.erb",
81
- :hidden => true)
82
- page.publish
83
- create_route(page, portlet_name, "/#{@blog.name_for_path}/:year/:month/:day/:slug")
84
- create_portlet(page, portlet_name, BlogPostPortlet)
85
- end
86
-
87
- # When the name of a Blog block changes, we need to change the Post page route.
88
- # We also change the *names* of the section and pages that hold the blog block and
89
- # post portlet because presumably, by changing the name of the blog, the intention
90
- # was to reflect this name change in breadcrumbs and menus.
91
- #
92
- # Note that no other routes or paths are updated. This is intentional to be consistent
93
- # with how BrowserCMS behaves when a Section or Page names change: paths are not
94
- # updated automatically.
95
- def update_section_pages_and_route(blog)
96
- if blog.name_changed?
97
- old_blog_name = blog.name_was
98
-
99
- Section.find_by_name(old_blog_name).update_attribute(:name, blog.name)
100
- PageRoute.find_by_name("#{old_blog_name}: Post").update_attribute(:name, "#{blog.name}: Post")
101
-
102
- page = Page.find_by_name("#{old_blog_name}: Post")
103
- page.update_attribute(:name, "#{blog.name}: Post")
104
- page.publish
105
-
106
- page = Page.find_by_name(old_blog_name)
107
- page.update_attribute(:name, blog.name)
108
- page.publish
109
- end
110
- end
111
-
112
- def reload_routes
113
- PageRoute.reload_routes
114
- end
115
-
116
- def create_route(page, name, pattern)
117
- route = page.page_routes.build(:name => name, :pattern => pattern, :code => "")
118
- route.save!
119
- route.add_condition(:method, "get").save
120
- route.add_requirement(:year, '\d{4,}') if pattern.include?(":year")
121
- route.add_requirement(:month, '\d{2,}') if pattern.include?(":month")
122
- route.add_requirement(:day, '\d{2,}') if pattern.include?(":day")
123
- route.requirements.each(&:save)
124
- end
125
-
126
- def create_portlet(page, name, portlet_class)
127
- portlet_class.create!(
128
- :name => "#{name} Portlet",
129
- :blog_id => @blog.id,
130
- :template => portlet_class.default_template,
131
- :connect_to_page_id => page.id,
132
- :connect_to_container => "main",
133
- :publish_on_save => true)
134
- end
135
- end
136
-
137
-
138
-
139
-
140
-
@@ -1,113 +0,0 @@
1
- class BlogPost < ActiveRecord::Base
2
- acts_as_content_block :taggable => true
3
-
4
- belongs_to_attachment
5
- def set_attachment_file_path
6
- # The default behavior is use /attachments/file.txt for the attachment path,
7
- # assuming file.txt was the name of the file the user uploaded
8
- # You should override this with your own strategy for setting the attachment path
9
- super
10
- end
11
-
12
- def set_attachment_section
13
- # The default behavior is to put all attachments in the root section
14
- # Override this method if you would like to change that
15
- super
16
- end
17
-
18
-
19
- before_save :set_published_at
20
-
21
- belongs_to :blog
22
- belongs_to_category
23
- belongs_to :author, :class_name => "User"
24
- has_many :comments, :class_name => "BlogComment", :foreign_key => "post_id"
25
-
26
- before_validation :set_slug
27
- validates_presence_of :name, :slug, :blog_id, :author_id
28
-
29
- scope :published_between, lambda { |start, finish|
30
- { :conditions => [
31
- "blog_posts.published_at >= ? AND blog_posts.published_at < ?",
32
- start, finish ] }
33
- }
34
-
35
- scope :not_tagged_with, lambda { |tag| {
36
- :conditions => [
37
- "blog_posts.id not in (
38
- SELECT taggings.taggable_id FROM taggings
39
- JOIN tags ON tags.id = taggings.tag_id
40
- WHERE taggings.taggable_type = 'BlogPost'
41
- AND (tags.name = ?)
42
- )",
43
- tag
44
- ]
45
- } }
46
-
47
- INCORRECT_PARAMETERS = "Incorrect parameters. This is probably because you are trying to view the " +
48
- "portlet through the CMS interface, and so we have no way of knowing what " +
49
- "post(s) to show"
50
-
51
- delegate :editable_by?, :to => :blog
52
-
53
- def set_published_at
54
- if !published_at && publish_on_save
55
- self.published_at = Time.now
56
- end
57
- end
58
-
59
- # This is necessary because, oddly, the publish! method in the Publishing behaviour sends an update
60
- # query directly to the database, bypassing callbacks, so published_at does not get set by our
61
- # set_published_at callback.
62
- def after_publish_with_set_published_at
63
- if published_at.nil?
64
- self.published_at = Time.now
65
- self.save!
66
- end
67
- after_publish_without_set_published_at if respond_to? :after_publish_without_set_published_at
68
- end
69
- if instance_methods.map(&:to_s).include? 'after_publish'
70
- alias_method_chain :after_publish, :set_published_at
71
- else
72
- alias_method :after_publish, :after_publish_with_set_published_at
73
- end
74
-
75
- def self.default_order
76
- "created_at desc"
77
- end
78
-
79
- def self.columns_for_index
80
- [ {:label => "Name", :method => :name, :order => "name" },
81
- {:label => "Published At", :method => :published_label, :order => "published_at" } ]
82
- end
83
-
84
- def published_label
85
- published_at ? published_at.to_s(:date) : nil
86
- end
87
-
88
- def set_slug
89
- self.slug = name.to_slug
90
- end
91
-
92
- def path
93
- send("#{blog.name_for_path}_post_path", route_params)
94
- end
95
- def route_name
96
- "#{blog.name_for_path}_post"
97
- end
98
- def route_params
99
- {:year => year, :month => month, :day => day, :slug => slug}
100
- end
101
-
102
- def year
103
- published_at.strftime("%Y") unless published_at.blank?
104
- end
105
-
106
- def month
107
- published_at.strftime("%m") unless published_at.blank?
108
- end
109
-
110
- def day
111
- published_at.strftime("%d") unless published_at.blank?
112
- end
113
- end
@@ -1,5 +0,0 @@
1
- <%= f.cms_drop_down :post_id, BlogPost.all(:order => "name").map{|p| [p.name, p.id]} %>
2
- <%= f.cms_text_field :author %>
3
- <%= f.cms_text_field :email %>
4
- <%= f.cms_text_field :url %>
5
- <%= f.cms_text_area :body %>
@@ -1,2 +0,0 @@
1
- <%= link_to h(@content_block.post.name), cms_blog_post_path(@content_block.post) %>
2
- <p><%=h @content_block.body.html_safe %></p>
@@ -1,17 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
5
- <title><%= page_title %></title>
6
- <%= yield :html_head %>
7
- </head>
8
- <body style="margin: 0; padding: 0; text-align: center;">
9
- <%= cms_toolbar %>
10
- <div id="wrapper" style="width: 700px; margin: 0 auto; text-align: left; padding: 30px">
11
- Breadcrumbs: <%= render_breadcrumbs %>
12
- Main Menu: <%= render_menu %>
13
- <h1><%= page_title %></h1>
14
- <%= container :main %>
15
- </div>
16
- </body>
17
- </html>
data/doc/README_FOR_APP DELETED
@@ -1,2 +0,0 @@
1
- Use this README file to introduce your application and point to useful places in the API for learning more.
2
- Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
@@ -1,77 +0,0 @@
1
- # Ideally, we would create a new migration whenever we wanted to make changes to an existing
2
- # migration that is already in circulation, instead of simply editing the existing migrations
3
- # and publishing the new version, because doing rake db:migrate:redo VERSION=20090415000000,
4
- # etc. on each updated migration is not only a pain but will probably result in more data being
5
- # lost than is strictly necessary -- assuming the migrations work correctly at all.
6
- #
7
- # On the other hand, there's something pretty compelling about "fixing" the migration so that
8
- # it doesn't have any useless steps that are just going to get reverted by the next migration.
9
- #
10
- # There is also the problem of model dependencies: you can't safely remove a model in the same
11
- # commit that you use that model in a migration (f.e., Model.destroy_all). Even if you remove it
12
- # in the following commit, it's only safe if people check out every intermediate version and run
13
- # db:migrate at each version, instead of simply checking out the tip version and then running
14
- # db:migrate. And people don't do that.
15
- #
16
- # Anyway, I guess we assume that there are only a few brave souls out there who are already
17
- # using bcms_blog and hope for the best. Here is the "missing migration"; hopefully it will be
18
- # helpful to you.
19
- #
20
- # Run this script instead of re-running the changed migrations with rake db:migrate:redo so that
21
- # your blog data is not destroyed.
22
- #
23
- # Usage: ./script/runner 'require "/path/to/bcms_blog/doc/migrate_to_20100427.rb"'
24
-
25
- require 'pp'
26
-
27
- Page # trigger auto-loading
28
- # At the time of this writing, these associations are missing :dependent => :destroy
29
- class Page
30
- has_many :page_routes, :dependent => :destroy
31
- end
32
- class PageRoute
33
- has_many :requirements, :class_name => "PageRouteRequirement", :dependent => :destroy
34
- has_many :conditions, :class_name => "PageRouteCondition", :dependent => :destroy
35
- end
36
-
37
- # Added these here because these classes will be removed by the next commit, so if anyone tried to run this script in future versions it would have a missing constant error unless we keep these class definitions around
38
- class BlogPostsInCategoryPortlet < Portlet; end
39
- class BlogPostsWithTagPortlet < Portlet; end
40
- class BlogPostPortlet < Portlet; end
41
- class BlogPostsInDayPortlet < Portlet; end
42
- class BlogPostsInMonthPortlet < Portlet; end
43
- class BlogPostsInYearPortlet < Portlet; end
44
-
45
- class MigrateTo20100427 < ActiveRecord::Migration
46
- def self.up
47
- drop_table :blog_group_membership_versions
48
-
49
- PageRouteOption.all.each {|a| a.destroy unless a.page_route }
50
-
51
- puts "Destroying portlets, pages, page_routes left over from old version of bcms_blog..."
52
- puts "(*Not* destroying any existing Blogs, pages on which Blogs are connected, or BlogPosts)"
53
- portlets = [BlogPostPortlet, BlogPostsInCategoryPortlet, BlogPostsWithTagPortlet, BlogPostsInDayPortlet, BlogPostsInMonthPortlet, BlogPostsInYearPortlet]
54
- #pp portlets.map(&:all).flatten.map(&:connected_pages).flatten.map(&:page_routes).flatten.each(&:destroy)
55
- pp portlets.map(&:all).flatten.map(&:connected_pages).flatten.each(&:destroy)
56
- pp portlets.map(&:all).flatten.each(&:destroy)
57
-
58
- # Something like this might not work if they have moved their Blog page to a different section or to no section, so we better let users resolve this manually...
59
- #Blog.all.map(&:connected_pages).flatten.each do |page|
60
- # page.hidden = true
61
- # page.save!
62
- # page.section.hidden = false
63
- # page.section.save!
64
- #end
65
-
66
- puts "Calling after_create on each Blog in the system..."
67
- Blog.all.each do |blog|
68
- puts "#{blog}..."
69
- blog.send :after_create
70
- end
71
- end
72
-
73
- def self.down
74
- end
75
- end
76
-
77
- MigrateTo20100427.up
@@ -1,48 +0,0 @@
1
- v1.2.0
2
- - Upgrade to be compatible with BrowserCMS 3.3 (aka Rails 3)
3
-
4
- v1.1.1
5
-
6
- - Blog partials and templates no longer include any css style declarations
7
- - Fixed browsing by tags, categories and dates
8
- - Fixed bug on page route conditions and requirements when creating a blog
9
- - Tests refactoring. Tests now depend on bcms_support gem
10
-
11
- v1.1.0
12
-
13
- This version introduces significant changes and improvements over version 1.0.0
14
- and lays the groundwork for a more sophisticated blogging platform for BrowserCMS.
15
-
16
- Notable Features:
17
- =================
18
-
19
- 1. A Blog and supporting structure (sections, pages, page routes, etc.) and data are no longer
20
- created as part of the modules's installation process. When running the module's migrations,
21
- only the following items are created:
22
-
23
- * blogs, blog_posts and blog_comment tables (and corresponding tables to hold versioning data)
24
- * blog_group_memberships table
25
- * Blog, BlogPost and BlogComment content types
26
- * Blog Post category type
27
-
28
- 2. It is only until a Blog is created when a corresponding section, pages, page routes and portlets are created.
29
- Each blog has its own section, pages and page routes, which allows for multiple blogs to be created.
30
-
31
- 3. It is now possible to add attachments to blog posts.
32
-
33
- 4. Comments are moderated by default using BrowserCMS' default behaviors. However, when creating a Blog,
34
- users can specify whether comments should be published automatically.
35
-
36
- 5. The module now uses BrowserCMS' permissions framework to specify if a particular user is able to
37
- create or edit Blogs and BlogPosts.
38
-
39
- 6. Portlets have been improved to match common standard blog publishing templates.
40
-
41
- For a complete rundown and rationale behind the changes introduced, please refer to:
42
- https://browsermedia.lighthouseapp.com/projects/28481/tickets/163-review-and-integrate-changes-to-the-blog-module
43
-
44
- Contributors:
45
- =============
46
- Tyler Rick
47
- Jon Leighton
48
- Juan Alvarez
@@ -1,10 +0,0 @@
1
- module Cms::Routes
2
- def routes_for_bcms_blog
3
- match '/blog/feeds', :to=>"feeds#index", :defaults=>{:format => "rss"}, :as=>'blog_feeds'
4
- namespace(:cms) do
5
- content_blocks :blogs
6
- content_blocks :blog_posts
7
- content_blocks :blog_comments
8
- end
9
- end
10
- end