acts_as_debatable 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +10 -0
  3. data/README.md +31 -19
  4. data/acts_as_debatable.gemspec +19 -0
  5. data/app/controllers/comments_controller.rb +60 -0
  6. data/app/helper/comments_helper.rb +18 -0
  7. data/app/models/comment.rb +25 -0
  8. data/app/views/comments/_edit_form.html.erb +22 -0
  9. data/app/views/comments/_form.html.erb +44 -0
  10. data/app/views/comments/_show.html.erb +40 -0
  11. data/app/views/comments/edit.html.erb +3 -0
  12. data/config/locales/en.yml +17 -0
  13. data/config/routes.rb +4 -0
  14. data/public/stylesheets/debate_style.css +15 -0
  15. data/public/stylesheets/sass/debate_style.sass +11 -0
  16. data/test/acts_as_debatable_test.rb +7 -0
  17. data/test/dummy/Rakefile +7 -0
  18. data/test/dummy/app/controllers/application_controller.rb +3 -0
  19. data/test/dummy/app/helpers/application_helper.rb +2 -0
  20. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/test/dummy/config.ru +4 -0
  22. data/test/dummy/config/application.rb +45 -0
  23. data/test/dummy/config/boot.rb +10 -0
  24. data/test/dummy/config/database.yml +22 -0
  25. data/test/dummy/config/environment.rb +5 -0
  26. data/test/dummy/config/environments/development.rb +26 -0
  27. data/test/dummy/config/environments/production.rb +49 -0
  28. data/test/dummy/config/environments/test.rb +35 -0
  29. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  30. data/test/dummy/config/initializers/inflections.rb +10 -0
  31. data/test/dummy/config/initializers/mime_types.rb +5 -0
  32. data/test/dummy/config/initializers/secret_token.rb +7 -0
  33. data/test/dummy/config/initializers/session_store.rb +8 -0
  34. data/test/dummy/config/locales/en.yml +5 -0
  35. data/test/dummy/config/routes.rb +58 -0
  36. data/test/dummy/public/404.html +26 -0
  37. data/test/dummy/public/422.html +26 -0
  38. data/test/dummy/public/500.html +26 -0
  39. data/test/dummy/public/favicon.ico +0 -0
  40. data/test/dummy/public/javascripts/application.js +2 -0
  41. data/test/dummy/public/javascripts/controls.js +965 -0
  42. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  43. data/test/dummy/public/javascripts/effects.js +1123 -0
  44. data/test/dummy/public/javascripts/prototype.js +6001 -0
  45. data/test/dummy/public/javascripts/rails.js +191 -0
  46. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  47. data/test/dummy/script/rails +6 -0
  48. data/test/integration/navigation_test.rb +7 -0
  49. data/test/support/integration_case.rb +5 -0
  50. data/test/test_helper.rb +22 -0
  51. metadata +81 -12
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", ">= 3.0.1"
4
+ gem "capybara", ">= 0.4.0"
5
+ gem "sqlite3-ruby", :require => "sqlite3"
6
+
7
+
8
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
9
+ # gem 'ruby-debug'
10
+ # gem 'ruby-debug19'
data/README.md CHANGED
@@ -1,7 +1,13 @@
1
1
  Acts\_as\_debatable
2
2
  ===================
3
3
 
4
- This plugin is still on its pre-alpha stage, which means that you may use it on your own risk.
4
+ This plugin is still on its pre-alpha stage, which means that you may use it on your own risk.
5
+
6
+ ## Prerequirements
7
+
8
+ You have to have a User model with fields: admin:boolean, username:string (or login:string).
9
+ We need admin field for approving comments. Username field gives us a chance to display something like "This comment was written by USERNAME".
10
+ You can use 'login' field instead of 'username' as acts\_as\_debatable is looking for that name if it can't find the latter.
5
11
 
6
12
  ## Install
7
13
 
@@ -10,14 +16,17 @@ First of all you'll need to add some gems. Add this to your app's Gemfile **befo
10
16
  gem 'devise'
11
17
  gem 'ancestry'
12
18
 
19
+ Acts\_as\_debatable doesn't make any use of Devise except it uses its user\_signed\_in? and current\_user helper methods. If you can provide that methods on your own or your authentication module has those methods there is no need to add gem 'devise'!
20
+ Gem Ancestry will be used for comments threading.
21
+
13
22
  then add:
14
23
 
15
- gem 'acts_as_debatable', :git => 'git://github.com/espresse/acts_as_debatable.git'
24
+ gem 'acts_as_debatable', :git=> 'git://github.com/espresse/acts_as_debatable.git'
16
25
 
17
26
  Run
18
27
 
19
28
  bundle install
20
- rails g acts_as_debatable:migrations
29
+ rails g acts_as_debatable:migration
21
30
  rake db:migrate
22
31
 
23
32
  Now you're ready to rock your models.
@@ -36,41 +45,44 @@ So far so good. Next, let's show comments on the page.
36
45
 
37
46
  In your show.html.erb file add these partials:
38
47
 
39
- <%= render :partial => "comments/show", :locals => {:model => @article} %>
40
- <%= render :partial => "comments/form", :locals => {:model => @article} %>
41
- Change @article according to your model variable.
42
-
43
- You can overwrite them in yours app/views/comments/.
44
-
45
- As there is no autoinstall yet, you have to copy all files from public/* to your app public folder. This will change in future versions.
48
+ <%= show_debate @article %>
49
+ <%= debate_form @article %>
50
+ Change @article according to what your controller returns.
46
51
 
47
- You can also use those methods:
52
+ There are several methods created to help you with comments:
48
53
 
49
- Your\_class.latest\_debate - this will give you 10 last comments on Model
50
- Your\_class.count\_comments - self-explaining; a number of all comments on Model
54
+ Your\_class.latest\_debate - this will give you 10 last comments in Model
55
+ Your\_class.count\_comments - self-explaining; a number of all comments in Model
51
56
 
52
57
  @your\_class\_object.has\_comments? - returns true if there is at least one comment and false if not
53
58
  @your\_class\_object.latest\_debate - returns last 10 comments for this object
54
59
 
60
+ User.find(1).comments will return all comments wrote by User with id 1.
61
+
55
62
  ## I18n
56
63
 
57
64
  Take a look at config/locales/en.yml in this gem. You'll need to translate the file to have it localized.
58
65
 
66
+ ## How to change comments look&feel?
67
+
68
+ There is some basic CSS, you can find them in gems public directory. Feel free to use them in your application. If you want to do so, you need to copy them to your app's public folder. Change them to suits your needs.
69
+
70
+ ## How to approve comments?
71
+
72
+ As for now, approving is possible only in rails console. You can overwrite comments controller in yours app/controllers/comments_controller.rb and customize approving.
73
+
59
74
  ## TODO
60
75
 
61
- - better db indexing
62
- - better validation
63
- - comments approval system
64
76
  - CSS/JS
65
77
  - better use of ancestry gem
66
78
  - ajax for creating/updating comments
67
79
  - akismet spam checking
68
80
  - recaptcha
69
- - User model should have a field username/login/full_name, now we are displaying user's email address, which is not so wise...
70
- - for approval there's a need to have an admin field in User's model?
81
+ - notifications
82
+ - votes
71
83
 
72
84
  ##Bugs? Features?
73
85
 
74
86
  Please post an issue on http://github.com/espresse/acts_as_debatable/issues
75
87
 
76
- Copyright © 2011 Michał Ostrowski, released under the MIT license
88
+ Copyright © 2011 Michał Ostrowski, released under the MIT license
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "acts_as_debatable"
5
+ s.version = "0.1.0"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Michał Ostrowski"]
8
+ s.email = ["michol@linuxcsb.org"]
9
+ s.summary = %q{Comment system for Ruby On Rails}
10
+ s.description = %q{Ruby on Rails gem to provide simple and easy commenting system for any model.}
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ #s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency("bundler", ["~> 1.0"])
18
+ end
19
+
@@ -0,0 +1,60 @@
1
+ class CommentsController < ActionController::Base
2
+
3
+ unloadable
4
+
5
+ before_filter :find_comment, :except => [:create, :new]
6
+
7
+ def new
8
+ @comment = Comment.new
9
+ end
10
+
11
+ def create
12
+ @comment = Comment.new(params[:comment])
13
+
14
+ if @comment.save
15
+ if @comment.approved
16
+ flash[:notice] = t("comment_ok")
17
+ else
18
+ flash[:notice] = t("awaiting_moderation")
19
+ end
20
+ redirect_to :back
21
+ else
22
+ redirect_to :back, :alert => t("fill_out_fields")
23
+ end
24
+ end
25
+
26
+ def edit
27
+ if @comment.user_id
28
+ unless @comment.user.id == current_user.id
29
+ redirect_to :back
30
+ end
31
+ else
32
+ redirect_to :back
33
+ end
34
+ store_location
35
+ end
36
+
37
+ def update
38
+ if @comment.update_attributes(params[:comment])
39
+ redirect_back
40
+ else
41
+ render :action => :edit
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def find_comment
48
+ @comment = Comment.find(params[:id])
49
+ end
50
+
51
+ def store_location
52
+ session[:return_to] = request.referer if request.get?
53
+ end
54
+
55
+ def redirect_back
56
+ redirect_to(session[:return_to])
57
+ end
58
+
59
+
60
+ end
@@ -0,0 +1,18 @@
1
+ module CommentsHelper
2
+ def link_to_comment(comment)
3
+
4
+ end
5
+
6
+ def small_avatar_url(email)
7
+ gravatar_id = Digest::MD5::hexdigest(email).downcase
8
+ "http://gravatar.com/avatar/#{gravatar_id}.png?s=24"
9
+ end
10
+
11
+ def show_debate(model)
12
+ render :partial => "comments/show", :locals => {:model => model}
13
+ end
14
+
15
+ def debate_form(model)
16
+ render :partial => "comments/form", :locals => {:model => model}
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :commentable, :polymorphic => true
3
+ belongs_to :user
4
+
5
+ validates_presence_of :content
6
+ validates_presence_of :author_email, :author, :unless => :user_id
7
+ validates_format_of :author_email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :on => :create, :alert => "is invalid", :unless => :user_id
8
+
9
+ #comments can be approved (set to true), not approved (set to false) and awaiting approval (nil)
10
+ scope :approved, where(:approved => true)
11
+ scope :awaiting_approval, where(:approved => nil)
12
+ scope :not_approved, where(:approved => false)
13
+
14
+ before_save :comment_approval
15
+
16
+ def comment_approval
17
+ if user_id
18
+ self.approved = true
19
+ end
20
+ end
21
+
22
+ #db is prepared for has_ancestry although Comment is not fully prepared to use it
23
+ #has_ancestry
24
+ end
25
+
@@ -0,0 +1,22 @@
1
+ <%= form_for(@comment) do |f| %>
2
+ <% if @comment.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @comment.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field" id="debate_content">
15
+ <%= f.label :content %><br />
16
+ <%= f.text_area :content %>
17
+ </div>
18
+
19
+ <div class="actions">
20
+ <%= f.submit t("update_comment")%>
21
+ </div>
22
+ <% end %>
@@ -0,0 +1,44 @@
1
+ <a name="commentform"></a>
2
+ <div class="debate_form">
3
+ <%= form_for [@commentable, Comment.new] do |f| %>
4
+
5
+ <!-- move this to partial _alert.html.erb -->
6
+ <p id="notice"><%= alert %><%= notice %></p>
7
+ <!-- -->
8
+
9
+ <% unless user_signed_in? %>
10
+ <div class="field" id="debate_author">
11
+ <%= f.label t("author") %><br />
12
+ <%= f.text_field :author %>
13
+ </div>
14
+ <div class="field" id="debate_author_url">
15
+ <%= f.label t("author_url") %><br />
16
+ <%= f.text_field :author_url %>
17
+ </div>
18
+ <div class="field" id="debate_author_email">
19
+ <%= f.label t("author_email") %><br />
20
+ <%= f.text_field :author_email %>
21
+ </div>
22
+
23
+ <% else %>
24
+ <%= f.hidden_field :user_id, :value => current_user.id %>
25
+
26
+ <% end %>
27
+
28
+
29
+ <div class="field" id="debate_content">
30
+ <%= f.label t("content") %><br />
31
+ <%= f.text_area :content %>
32
+ </div>
33
+
34
+
35
+ <%= f.hidden_field :commentable_type, :value => model.class %>
36
+ <%= f.hidden_field :commentable_id, :value => model.id %>
37
+ <%= f.hidden_field :user_ip, :value => request.remote_ip %>
38
+ <%= f.hidden_field :user_agent, :value => request.user_agent %>
39
+
40
+ <div class="actions">
41
+ <%= f.submit t("create_comment") %>
42
+ </div>
43
+ <% end %>
44
+ </div>
@@ -0,0 +1,40 @@
1
+
2
+ <div class="debate">
3
+ <a name="comments"><b><%= t("comments") %> - <%= model.comments.approved.count %> (<%= t("waiting_for_approval") %>: <%= model.comments.awaiting_approval.count %>)</b></a>
4
+
5
+ <% model.comments.approved.each do |comment| %>
6
+ <div class="comment depth<%= comment.ancestry_depth %>">
7
+
8
+ <div class="comment_header">
9
+ <a name="<%= comment.id %>">
10
+ <% if comment.user.blank? %>
11
+ <%= image_tag small_avatar_url("anonymous") %>
12
+ <% else %>
13
+ <%= image_tag(small_avatar_url(comment.user.email)) %>
14
+ <% end %>
15
+
16
+ <%= t("posted_on") %> <%= comment.created_at %>, <%= t("by") %>
17
+ <% if comment.user.blank? %>
18
+ <%= comment.author %></a>
19
+ <% else %>
20
+ <%= comment.user.email %>
21
+ <% if user_signed_in? %>
22
+ <%= link_to t("edit_comment"), edit_comment_path(comment) %>
23
+ <% end %>
24
+ <% end %>
25
+ </a>
26
+ </div>
27
+
28
+ <div class="comment_body">
29
+
30
+ <%= comment.content %>
31
+ </div>
32
+ <div style="clear: both"></div>
33
+ <div class="comment_footer">
34
+ <% if comment.created_at != comment.updated_at %>
35
+ <%= t("last_modified") %> <%= comment.updated_at %>
36
+ <% end %>
37
+ </div>
38
+ </div>
39
+ <% end %>
40
+ </div>
@@ -0,0 +1,3 @@
1
+ <h1>Editing Comment</h1>
2
+
3
+ <%= render 'edit_form' %>
@@ -0,0 +1,17 @@
1
+ en:
2
+ posted_on: Posted on
3
+ last_modified: Last modified
4
+ by: by
5
+ comments: Comments
6
+ edit_comment: Edit
7
+ comment_ok: Comment has been accepted
8
+ author: Author
9
+ author_email: Author's email
10
+ author_url: Author's www
11
+ content: Content
12
+ create_comment: Create Comment
13
+ awaiting_moderation: Your comment has been submited and is awaiting moderation.
14
+ fill_out_fields: Fields marked with asterix have to be filled out.
15
+ waiting_for_approval: waiting for approval
16
+ update_comment: Update Comment
17
+ answer: Answer
@@ -0,0 +1,4 @@
1
+ Rails.application.routes.draw do |map|
2
+ resources :comments
3
+ end
4
+
@@ -0,0 +1,15 @@
1
+ .debate .depth0 {
2
+ margin-left: 0px;
3
+ }
4
+
5
+ .debate .depth1 {
6
+ margin-left: 10px;
7
+ }
8
+
9
+ .debate .depth2 {
10
+ margin-left: 20px;
11
+ }
12
+
13
+ .debate .depth3 {
14
+ margin-left: 30px;
15
+ }
@@ -0,0 +1,11 @@
1
+ .debate .depth0
2
+ margin-left: 0px
3
+
4
+ .debate .depth1
5
+ margin-left: 10px
6
+
7
+ .debate .depth2
8
+ margin-left: 20px
9
+
10
+ .debate .depth3
11
+ margin-left: 30px
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class ActsAsDebatableTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, ActsAsDebatable
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>