rails_blog_engine 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +24 -0
  4. data/Guardfile +21 -0
  5. data/Procfile +1 -0
  6. data/TODO.txt +31 -0
  7. data/app/assets/images/rails_blog_engine/.gitkeep +0 -0
  8. data/app/controllers/rails_blog_engine/comments_controller.rb +1 -1
  9. data/app/controllers/rails_blog_engine/posts_controller.rb +1 -1
  10. data/lib/rails_blog_engine.rb +2 -0
  11. data/lib/rails_blog_engine/version.rb +1 -1
  12. data/rails_blog_engine.gemspec +64 -0
  13. data/script/rails +6 -0
  14. data/spec/acceptance/acceptance_helper.rb +4 -0
  15. data/spec/acceptance/rails_blog_engine/posts_admin_spec.rb +33 -0
  16. data/spec/acceptance/rails_blog_engine/posts_spec.rb +74 -0
  17. data/spec/acceptance/rails_blog_engine/spam_filtering_spec.rb +110 -0
  18. data/spec/acceptance/support/helpers.rb +18 -0
  19. data/spec/acceptance/support/paths.rb +5 -0
  20. data/spec/controllers/rails_blog_engine/comments_controller_spec.rb +22 -0
  21. data/spec/controllers/rails_blog_engine/posts_controller_spec.rb +81 -0
  22. data/spec/dummy/Rakefile +7 -0
  23. data/spec/dummy/app/assets/javascripts/application.js +10 -0
  24. data/spec/dummy/app/assets/stylesheets/application.css +8 -0
  25. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  26. data/spec/dummy/app/controllers/home_controller.rb +4 -0
  27. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  28. data/spec/dummy/app/mailers/.gitkeep +0 -0
  29. data/spec/dummy/app/models/.gitkeep +0 -0
  30. data/spec/dummy/app/models/ability.rb +11 -0
  31. data/spec/dummy/app/models/user.rb +9 -0
  32. data/spec/dummy/app/views/home/index.html.haml +2 -0
  33. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  34. data/spec/dummy/config.ru +4 -0
  35. data/spec/dummy/config/application.rb +54 -0
  36. data/spec/dummy/config/boot.rb +10 -0
  37. data/spec/dummy/config/database.yml +25 -0
  38. data/spec/dummy/config/environment.rb +5 -0
  39. data/spec/dummy/config/environments/development.rb +30 -0
  40. data/spec/dummy/config/environments/production.rb +60 -0
  41. data/spec/dummy/config/environments/test.rb +42 -0
  42. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/spec/dummy/config/initializers/devise.rb +211 -0
  44. data/spec/dummy/config/initializers/inflections.rb +10 -0
  45. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  46. data/spec/dummy/config/initializers/rails_blog_engine.rb +13 -0
  47. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  48. data/spec/dummy/config/initializers/session_store.rb +8 -0
  49. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  50. data/spec/dummy/config/locales/devise.en.yml +58 -0
  51. data/spec/dummy/config/locales/en.yml +5 -0
  52. data/spec/dummy/config/routes.rb +6 -0
  53. data/spec/dummy/db/migrate/20110913113004_devise_create_users.rb +28 -0
  54. data/spec/dummy/db/schema.rb +67 -0
  55. data/spec/dummy/lib/assets/.gitkeep +0 -0
  56. data/spec/dummy/log/.gitkeep +0 -0
  57. data/spec/dummy/public/404.html +26 -0
  58. data/spec/dummy/public/422.html +26 -0
  59. data/spec/dummy/public/500.html +26 -0
  60. data/spec/dummy/public/favicon.ico +0 -0
  61. data/spec/dummy/script/rails +6 -0
  62. data/spec/helpers/rails_blog_engine/application_helper_spec.rb +56 -0
  63. data/spec/helpers/rails_blog_engine/comments_helper_spec.rb +14 -0
  64. data/spec/helpers/rails_blog_engine/posts_helper_spec.rb +14 -0
  65. data/spec/lib/generators/rails_blog_engine/install_generator_spec.rb +78 -0
  66. data/spec/lib/rails_blog_engine/filters/base_spec.rb +13 -0
  67. data/spec/lib/rails_blog_engine/filters/code_spec.rb +16 -0
  68. data/spec/lib/rails_blog_engine/filters_spec.rb +58 -0
  69. data/spec/models/rails_blog_engine/comment_spec.rb +84 -0
  70. data/spec/models/rails_blog_engine/post_spec.rb +121 -0
  71. data/spec/spec_helper.rb +36 -0
  72. data/spec/support/blueprints.rb +25 -0
  73. data/spec/support/javascript.rb +27 -0
  74. data/spec/support/vcr.rb +8 -0
  75. data/spec/vcr_cassettes/rakismet-ham.yml +30 -0
  76. data/spec/vcr_cassettes/rakismet-spam.yml +30 -0
  77. data/spec/vcr_cassettes/rakismet-train-as-ham.yml +32 -0
  78. data/spec/vcr_cassettes/rakismet-train-as-spam.yml +32 -0
  79. metadata +175 -101
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /Gemfile.lock
2
+ /.bundle/
3
+ /.sass-cache/
4
+ /log/*.log
5
+ /pkg/
6
+ /spec/dummy/db/*.sqlite3
7
+ /spec/dummy/log/*.log
8
+ /spec/dummy/tmp/
9
+ /spec/dummy/.sass-cache/
10
+ /spec/tmp/
11
+ /.env
12
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,24 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in rails_blog_engine.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'ruby-debug19', :require => 'ruby-debug'
15
+
16
+ group :development do
17
+ # We need a version which doesn't create objects in separate threads,
18
+ # cache them, or do anything else that breaks database-cleaning
19
+ # transactions in Steak.
20
+ gem 'machinist', :git => 'https://github.com/notahat/machinist.git'
21
+
22
+ # This is an optional runtime depedency.
23
+ gem 'pygments', :git => 'https://github.com/nathany/pygments-gem.git'
24
+ end
data/Guardfile ADDED
@@ -0,0 +1,21 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
14
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
15
+ watch('spec/spec_helper.rb') { "spec" }
16
+ watch('config/routes.rb') { "spec/routing" }
17
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
18
+ # Capybara request specs
19
+ watch(%r{^app/views/(.+)/.*\.(erb|haml|builder)$}) { |m| ["spec/controllers/#{m[1]}_controller_spec.rb", "spec/requests/#{m[1]}_spec.rb"] }
20
+ end
21
+
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ web: bundle exec rails server -p $PORT
data/TODO.txt ADDED
@@ -0,0 +1,31 @@
1
+ Before public release
2
+
3
+ / Spam filtering for comments: rakismet
4
+ / Moderation by administrators
5
+ / Secure comment fields using attr_accessible
6
+ / Secure HTML in comments
7
+ X Table changes - Not going to collapse migrations, so there's no rush.
8
+ X Comment author_id polymorphic
9
+ X Comment state index
10
+ X Collapse migrations into 1 giant migration
11
+ / Quick refactoring pass
12
+ , Integrate into Kidd Software site
13
+
14
+ Needed for 3rd-party use
15
+
16
+ Generators
17
+ rails_blog_engine:templates
18
+ rails_blog_engine:filter
19
+ Config class? Either implement or remove initializer
20
+
21
+ Needed for use as a product or company blog
22
+
23
+ Caching
24
+ Editor polish
25
+ Auto-save
26
+ Publish / Unpublish button
27
+ , SEO best practices
28
+
29
+ Needed for 1.0
30
+
31
+ Recent articles list
File without changes
@@ -1,5 +1,5 @@
1
1
  module RailsBlogEngine
2
- class CommentsController < ApplicationController
2
+ class CommentsController < RailsBlogEngine::ApplicationController
3
3
  before_filter :load_post
4
4
 
5
5
  load_and_authorize_resource :class => "RailsBlogEngine::Comment"
@@ -1,5 +1,5 @@
1
1
  module RailsBlogEngine
2
- class PostsController < ApplicationController
2
+ class PostsController < RailsBlogEngine::ApplicationController
3
3
  before_filter :load_recently_published, :only => :index
4
4
  before_filter :load_by_permalink, :only => :show
5
5
 
@@ -15,4 +15,6 @@ require "rails_blog_engine/ability"
15
15
  require "rails_blog_engine/filters"
16
16
 
17
17
  module RailsBlogEngine
18
+ class Railtie < ::Rails::Railtie
19
+ end
18
20
  end
@@ -1,3 +1,3 @@
1
1
  module RailsBlogEngine
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,64 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "rails_blog_engine/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = "rails_blog_engine"
9
+ s.version = RailsBlogEngine::VERSION
10
+ s.authors = ["Eric Kidd"]
11
+ s.email = ["eric@kiddsoftware.com"]
12
+ s.homepage = "http://github.com/kiddsoftware/rails_blog_engine"
13
+ s.summary = "Rails 3.1 drop-in blog engine"
14
+ s.description = "Rails 3.1 drop-in blog engine for existing Rails applications"
15
+
16
+ s.files = `git ls-files`.split("\n").sort
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # Rails 3.1.
22
+ s.add_dependency "rails", "~> 3.1.0"
23
+
24
+ # Asset pipeline. We use all the standard gems plus HAML.
25
+ s.add_dependency "jquery-rails", "~> 1.0"
26
+ s.add_dependency "sass-rails", "~> 3.1"
27
+ s.add_dependency "coffee-script", "~> 2.2"
28
+ s.add_dependency "haml", "~> 3.1"
29
+
30
+ # Pagination.
31
+ s.add_dependency "kaminari", "~> 0.12.4"
32
+
33
+ # User accounts and authentication.
34
+ s.add_dependency "cancan", "~> 1.6"
35
+
36
+ # Spam filtering.
37
+ s.add_dependency "rakismet", "~> 1.1"
38
+
39
+ # Other useful libraries.
40
+ s.add_dependency "simple_form", "~> 1.4"
41
+ s.add_dependency "state_machine", "~> 1.0.0"
42
+ s.add_dependency "rdiscount", "~> 1.6"
43
+ s.add_dependency "sanitize", "~> 2.0"
44
+
45
+ # Development-only gems.
46
+ s.add_development_dependency "sqlite3"
47
+ s.add_development_dependency "devise"
48
+ s.add_development_dependency "steak"
49
+ s.add_development_dependency "foreman"
50
+ s.add_development_dependency "capybara-webkit", "~> 0.6.1"
51
+ s.add_development_dependency "database_cleaner"
52
+ s.add_development_dependency "shoulda-matchers"
53
+ s.add_development_dependency "generator_spec"
54
+ s.add_development_dependency "vcr", ">= 2.0.0.beta2"
55
+ s.add_development_dependency "fakeweb"
56
+ #s.add_development_dependency "machinist" (see Gemfile)
57
+ #s.add_development_dependency "pygments" (see Gemfile)
58
+
59
+ # Auto-running our unit tests when things change.
60
+ s.add_development_dependency "guard-rspec"
61
+ s.add_development_dependency "rb-inotify"
62
+ s.add_development_dependency "libnotify"
63
+ s.add_development_dependency "launchy"
64
+ end
data/script/rails ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ #!/usr/bin/env ruby
3
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
4
+
5
+ ENGINE_PATH = File.expand_path('../..', __FILE__)
6
+ load File.expand_path('../../spec/dummy/script/rails', __FILE__)
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ # Put your acceptance spec helpers inside spec/acceptance/support
4
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
@@ -0,0 +1,33 @@
1
+ require 'acceptance/acceptance_helper'
2
+
3
+ feature 'Posts admin', %q{
4
+ In order to publish information to the world
5
+ As a manager of the blog
6
+ I want to publish and manage posts
7
+ } do
8
+
9
+ background do
10
+ sign_in_as_admin
11
+ end
12
+
13
+ scenario 'Adding and editing new post', :js => true do
14
+ visit '/blog'
15
+
16
+ click_link "New Post"
17
+ fill_in 'Title', :with => 'Test Post'
18
+ fill_in 'Permalink', :with => 'test-post'
19
+ fill_in 'Body', :with => 'My post <img src="a.png">'
20
+ click_button 'Create Post'
21
+ page.should have_content("Test Post")
22
+ page.should have_content("by sue")
23
+ page.should have_content("My post")
24
+ page.should have_selector(:xpath, '//img[@src="a.png"]')
25
+
26
+ click_link "Edit"
27
+ fill_in 'Title', :with => 'New Title'
28
+ fill_in 'Body', :with => 'New Body'
29
+ click_button "Update Post"
30
+ page.should have_content('New Title')
31
+ page.should have_content('New Body')
32
+ end
33
+ end
@@ -0,0 +1,74 @@
1
+ require 'acceptance/acceptance_helper'
2
+
3
+ feature 'Posts', %q{
4
+ In order to learn intesting new things
5
+ As a site visitor
6
+ I want to read blog articles
7
+ } do
8
+
9
+ background do
10
+ published_at = Time.utc(2011, 01, 02, 03)
11
+ RailsBlogEngine::Post.make!(:title => "Test Post", :body => "_Body_ ",
12
+ :state => 'published',
13
+ :published_at => published_at,
14
+ :permalink => 'test')
15
+ end
16
+
17
+ scenario 'Viewing the index' do
18
+ visit '/blog'
19
+ page.should have_content("Test Post")
20
+ within('em') { page.should have_content("Body") }
21
+ page.should_not have_content("New Post")
22
+ end
23
+
24
+ scenario 'Navigating to a post' do
25
+ visit '/blog'
26
+ click_on "Test Post"
27
+ page.should have_content("Test Post")
28
+ page.should_not have_content("New Post")
29
+ within('em') { page.should have_content("Body") }
30
+ page.should_not have_content("Edit Post")
31
+ end
32
+
33
+ scenario 'Linking to a post directly' do
34
+ visit '/blog/2011/01/02/test'
35
+ page.should have_content("Test Post")
36
+ end
37
+
38
+ scenario 'Looking for posts on page 2' do
39
+ # Force our original post off the front page.
40
+ 5.times { RailsBlogEngine::Post.make!(:published) }
41
+
42
+ visit '/blog'
43
+ page.should_not have_content("Test Post")
44
+ click_on "Next"
45
+ page.should have_content("Test Post")
46
+ current_path.should == '/blog/page/2'
47
+ end
48
+
49
+ scenario 'Adding a comment' do
50
+ visit '/blog'
51
+ click_on 'Comment'
52
+ fill_in "Your name", :with => "Jane Doe"
53
+ fill_in "Comment", :with => "Test comment"
54
+ click_on "Post Comment"
55
+ page.should have_content("Jane Doe")
56
+ page.should have_content("Test comment")
57
+
58
+ # Change comment link text.
59
+ visit '/blog'
60
+ click_on "1 comment"
61
+ page.should have_content("Jane Doe")
62
+ end
63
+
64
+ scenario 'Validating a comment' do
65
+ visit '/blog'
66
+ click_on 'Comment'
67
+ click_on 'Post Comment'
68
+ page.should have_content("can't be blank")
69
+ fill_in "Your name", :with => "Jane Doe"
70
+ fill_in "Comment", :with => "Test comment"
71
+ click_on "Post Comment"
72
+ page.should have_content("Jane Doe")
73
+ end
74
+ end
@@ -0,0 +1,110 @@
1
+ require 'acceptance/acceptance_helper'
2
+
3
+ feature 'Spam filtering', %q{
4
+ In order to keep my site free of spam
5
+ As a manager of the blog
6
+ I want to identify spam posts and hide them automatically
7
+ } do
8
+
9
+ background do
10
+ @post = RailsBlogEngine::Post.make!(:published, :title => "Example post")
11
+ visit '/blog'
12
+ click_on "Example post"
13
+ end
14
+
15
+ def enable_spam_filter
16
+ Rakismet.key = "fakekey"
17
+ Rakismet.url = "http://www.example.com/"
18
+ end
19
+
20
+ def disable_spam_filter
21
+ Rakismet.key = nil
22
+ Rakismet.url = nil
23
+ end
24
+
25
+ def post_ham_comment
26
+ fill_in "Your name", :with => "Jane Doe"
27
+ fill_in "Comment", :with => "An interesting and legitimate post."
28
+ click_on "Post Comment"
29
+ end
30
+
31
+ def post_spam_comment
32
+ fill_in "Your name", :with => "viagra-test-123"
33
+ fill_in "Comment", :with => "Buy toner cartridges today!"
34
+ click_on "Post Comment"
35
+ end
36
+
37
+ def last_comment
38
+ @last_comment ||= RailsBlogEngine::Comment.last
39
+ end
40
+
41
+ scenario 'Posting a real comment' do
42
+ enable_spam_filter
43
+ VCR.use_cassette('rakismet-ham') { post_ham_comment }
44
+ last_comment.should be_filtered_as_ham
45
+ page.should have_content(last_comment.body)
46
+ page.should_not have_content("moderation")
47
+ end
48
+
49
+ scenario 'Posting a spam comment' do
50
+ enable_spam_filter
51
+ VCR.use_cassette('rakismet-spam') { post_spam_comment }
52
+ last_comment.should be_filtered_as_spam
53
+ page.should_not have_content(last_comment.body)
54
+ page.should have_content("moderation")
55
+ end
56
+
57
+ scenario 'Posting a comment without configuring the spam filter' do
58
+ disable_spam_filter
59
+ post_spam_comment
60
+ last_comment.should be_unfiltered
61
+ end
62
+
63
+ # Wait for the comment to have the specified state. This forces us to
64
+ # synchronize the current thread with the background thread the runs the
65
+ # webserver, which is helpful for ensuring that VCR cassettes will be
66
+ # left "in the VCR" until they've actually been used by the other thread.
67
+ def wait_for_comment_in_state(state)
68
+ Timeout.timeout(3) do
69
+ sleep 0.1 until RailsBlogEngine::Comment.where(:state => state.to_s).first
70
+ end
71
+ end
72
+
73
+ scenario 'Filtered as ham, mark as spam', :js => true do
74
+ enable_spam_filter
75
+ VCR.use_cassette('rakismet-ham', :match_requests_on => [:method]) do
76
+ post_spam_comment
77
+ wait_for_comment_in_state(:filtered_as_ham)
78
+ end
79
+ page.should have_content('viagra-test-123')
80
+ page.should have_selector('.ham')
81
+
82
+ sign_in_as_admin
83
+ VCR.use_cassette('rakismet-train-as-spam') do
84
+ click_on 'Spam'
85
+ wait_for_comment_in_state(:marked_as_spam)
86
+ end
87
+ page.should have_content('viagra-test-123')
88
+ page.should have_selector('.spam')
89
+ end
90
+
91
+ scenario 'Filtered as spam, mark as ham', :js => true do
92
+ enable_spam_filter
93
+ VCR.use_cassette('rakismet-spam', :match_requests_on => [:method]) do
94
+ post_ham_comment
95
+ wait_for_comment_in_state(:filtered_as_spam)
96
+ end
97
+ page.should_not have_content('Jane Doe')
98
+
99
+ sign_in_as_admin
100
+ page.should have_content('Jane Doe')
101
+ page.should have_selector('.spam')
102
+
103
+ VCR.use_cassette('rakismet-train-as-ham') do
104
+ click_on 'Not Spam'
105
+ wait_for_comment_in_state(:marked_as_ham)
106
+ end
107
+ page.should have_content('Jane Doe')
108
+ page.should have_selector('.ham')
109
+ end
110
+ end
@@ -0,0 +1,18 @@
1
+ module RailsBlogEngine::AcceptanceHelperMethods
2
+ # Put helper methods you need to be available in all acceptance specs here.
3
+
4
+ # In our test application, any user counts as an administrator.
5
+ def sign_in_as_admin
6
+ saved_path = current_path
7
+ visit '/users/sign_up'
8
+ fill_in 'Email', :with => "sue@example.com"
9
+ fill_in 'Password', :with => "password"
10
+ fill_in 'Password confirmation', :with => "password"
11
+ click_button 'Sign up'
12
+ visit saved_path
13
+ end
14
+ end
15
+
16
+ RSpec.configuration.include(RailsBlogEngine::AcceptanceHelperMethods,
17
+ :example_group =>
18
+ { :file_path => /spec\/acceptance/ })