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.
- data/.gitignore +6 -0
- data/Gemfile +10 -0
- data/README.md +31 -19
- data/acts_as_debatable.gemspec +19 -0
- data/app/controllers/comments_controller.rb +60 -0
- data/app/helper/comments_helper.rb +18 -0
- data/app/models/comment.rb +25 -0
- data/app/views/comments/_edit_form.html.erb +22 -0
- data/app/views/comments/_form.html.erb +44 -0
- data/app/views/comments/_show.html.erb +40 -0
- data/app/views/comments/edit.html.erb +3 -0
- data/config/locales/en.yml +17 -0
- data/config/routes.rb +4 -0
- data/public/stylesheets/debate_style.css +15 -0
- data/public/stylesheets/sass/debate_style.sass +11 -0
- data/test/acts_as_debatable_test.rb +7 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +22 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +26 -0
- data/test/dummy/config/environments/production.rb +49 -0
- data/test/dummy/config/environments/test.rb +35 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/javascripts/application.js +2 -0
- data/test/dummy/public/javascripts/controls.js +965 -0
- data/test/dummy/public/javascripts/dragdrop.js +974 -0
- data/test/dummy/public/javascripts/effects.js +1123 -0
- data/test/dummy/public/javascripts/prototype.js +6001 -0
- data/test/dummy/public/javascripts/rails.js +191 -0
- data/test/dummy/public/stylesheets/.gitkeep +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +7 -0
- data/test/support/integration_case.rb +5 -0
- data/test/test_helper.rb +22 -0
- metadata +81 -12
data/.gitignore
ADDED
data/Gemfile
ADDED
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
|
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:
|
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
|
-
<%=
|
40
|
-
<%=
|
41
|
-
Change @article according to your
|
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
|
-
|
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
|
50
|
-
Your\_class.count\_comments - self-explaining; a number of all comments
|
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
|
-
-
|
70
|
-
-
|
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,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
|
data/config/routes.rb
ADDED
data/test/dummy/Rakefile
ADDED
@@ -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
|