commontator 1.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/controllers/commontator/comments_controller.rb +3 -2
- data/app/controllers/commontator/comments_controller.rb~ +136 -0
- data/app/models/commontator/comment.rb +53 -36
- data/app/models/commontator/comment.rb~ +108 -0
- data/app/models/commontator/subscription.rb +8 -6
- data/app/models/commontator/subscription.rb~ +21 -0
- data/app/models/commontator/thread.rb +48 -44
- data/app/models/commontator/thread.rb~ +48 -47
- data/app/views/commontator/comments/_body.html.erb +1 -1
- data/app/views/commontator/comments/_body.html.erb~ +8 -0
- data/app/views/commontator/comments/_form.html.erb +1 -1
- data/app/views/commontator/comments/_form.html.erb~ +38 -0
- data/app/views/commontator/comments/_show.html.erb +1 -1
- data/app/views/commontator/comments/_show.html.erb~ +44 -0
- data/app/views/commontator/comments/_votes.html.erb +1 -1
- data/app/views/commontator/comments/_votes.html.erb~ +57 -0
- data/app/views/commontator/comments/delete.js.erb +1 -1
- data/app/views/commontator/comments/delete.js.erb~ +17 -0
- data/config/initializers/commontator.rb +11 -4
- data/config/initializers/commontator.rb~ +171 -0
- data/db/migrate/0_install.rb +23 -21
- data/db/migrate/0_install.rb~ +23 -21
- data/lib/commontator.rb +2 -0
- data/lib/commontator.rb~ +1 -1
- data/lib/commontator/acts_as_commontable.rb +7 -6
- data/lib/commontator/acts_as_commontable.rb~ +8 -6
- data/lib/commontator/acts_as_commontator.rb +4 -3
- data/lib/commontator/acts_as_commontator.rb~ +31 -0
- data/lib/commontator/version.rb +1 -1
- data/lib/commontator/version.rb~ +1 -1
- data/spec/app/controllers/commontator/comments_controller_spec.rb +61 -20
- data/spec/app/controllers/commontator/comments_controller_spec.rb~ +58 -21
- data/spec/app/models/commontator/comment_spec.rb +8 -7
- data/spec/app/models/commontator/comment_spec.rb~ +9 -8
- data/spec/app/models/commontator/thread_spec.rb +1 -1
- data/spec/app/models/commontator/thread_spec.rb~ +1 -1
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +16 -16
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +724 -0
- data/spec/dummy/log/test.log +41005 -0
- metadata +12 -2
@@ -51,6 +51,7 @@ module Commontator
|
|
51
51
|
# PUT /comments/1
|
52
52
|
def update
|
53
53
|
raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
|
54
|
+
@comment.editor = @user
|
54
55
|
|
55
56
|
respond_to do |format|
|
56
57
|
if @comment.update_attributes(params[:comment])
|
@@ -68,7 +69,7 @@ module Commontator
|
|
68
69
|
raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
|
69
70
|
|
70
71
|
@comment.errors.add(:base, 'This comment has already been deleted.') \
|
71
|
-
unless @comment.
|
72
|
+
unless @comment.delete_by(@user)
|
72
73
|
|
73
74
|
respond_to do |format|
|
74
75
|
format.html { redirect_to @thread }
|
@@ -81,7 +82,7 @@ module Commontator
|
|
81
82
|
raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
|
82
83
|
|
83
84
|
@comment.errors.add(:base, 'This comment is not deleted.') \
|
84
|
-
unless @comment.
|
85
|
+
unless @comment.undelete_by(@user)
|
85
86
|
|
86
87
|
respond_to do |format|
|
87
88
|
format.html { redirect_to @thread }
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Commontator
|
2
|
+
class CommentsController < ApplicationController
|
3
|
+
before_filter :get_thread, :only => [:new, :create]
|
4
|
+
before_filter :get_comment_and_thread, :except => [:new, :create]
|
5
|
+
before_filter :set_commontable_url, :only => :create
|
6
|
+
|
7
|
+
# GET /1/comments/new
|
8
|
+
def new
|
9
|
+
@comment = Comment.new
|
10
|
+
@comment.thread = @thread
|
11
|
+
@comment.creator = @user
|
12
|
+
|
13
|
+
raise SecurityTransgression unless @comment.can_be_created_by?(@user)
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html { redirect_to @thread }
|
17
|
+
format.js
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
# POST /1/comments
|
23
|
+
def create
|
24
|
+
@comment = Comment.new(params[:comment])
|
25
|
+
@comment.thread = @thread
|
26
|
+
@comment.creator = @user
|
27
|
+
|
28
|
+
raise SecurityTransgression unless @comment.can_be_created_by?(@user)
|
29
|
+
|
30
|
+
respond_to do |format|
|
31
|
+
if @comment.save
|
32
|
+
format.html { redirect_to @thread }
|
33
|
+
format.js
|
34
|
+
else
|
35
|
+
format.html { redirect_to @thread }
|
36
|
+
format.js { render :new }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# GET /comments/1/edit
|
42
|
+
def edit
|
43
|
+
raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
|
44
|
+
|
45
|
+
respond_to do |format|
|
46
|
+
format.html { redirect_to @thread }
|
47
|
+
format.js
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# PUT /comments/1
|
52
|
+
def update
|
53
|
+
raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
|
54
|
+
@comment.editor = @user
|
55
|
+
|
56
|
+
respond_to do |format|
|
57
|
+
if @comment.update_attributes(params[:comment])
|
58
|
+
format.html { redirect_to @thread }
|
59
|
+
format.js
|
60
|
+
else
|
61
|
+
format.html { redirect_to @thread }
|
62
|
+
format.js { render :edit }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# PUT /comments/1/delete
|
68
|
+
def delete
|
69
|
+
raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
|
70
|
+
|
71
|
+
@comment.errors.add(:base, 'This comment has already been deleted.') \
|
72
|
+
unless @comment.delete(@user)
|
73
|
+
|
74
|
+
respond_to do |format|
|
75
|
+
format.html { redirect_to @thread }
|
76
|
+
format.js { render :delete }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# PUT /comments/1/undelete
|
81
|
+
def undelete
|
82
|
+
raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
|
83
|
+
|
84
|
+
@comment.errors.add(:base, 'This comment is not deleted.') \
|
85
|
+
unless @comment.undelete_by(@user)
|
86
|
+
|
87
|
+
respond_to do |format|
|
88
|
+
format.html { redirect_to @thread }
|
89
|
+
format.js { render :delete }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# PUT /comments/1/upvote
|
94
|
+
def upvote
|
95
|
+
raise SecurityTransgression unless @comment.can_be_voted_on_by?(@user)
|
96
|
+
|
97
|
+
@comment.upvote_from @user
|
98
|
+
|
99
|
+
respond_to do |format|
|
100
|
+
format.html { redirect_to @thread }
|
101
|
+
format.js { render :vote }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# PUT /comments/1/downvote
|
106
|
+
def downvote
|
107
|
+
raise SecurityTransgression unless @comment.can_be_voted_on_by?(@user)
|
108
|
+
|
109
|
+
@comment.downvote_from @user
|
110
|
+
|
111
|
+
respond_to do |format|
|
112
|
+
format.html { redirect_to @thread }
|
113
|
+
format.js { render :vote }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# PUT /comments/1/unvote
|
118
|
+
def unvote
|
119
|
+
raise SecurityTransgression unless @comment.can_be_voted_on_by?(@user)
|
120
|
+
|
121
|
+
@comment.unvote :voter => @user
|
122
|
+
|
123
|
+
respond_to do |format|
|
124
|
+
format.html { redirect_to @thread }
|
125
|
+
format.js { render :vote }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def get_comment_and_thread
|
132
|
+
@comment = Comment.find(params[:id])
|
133
|
+
@thread = @comment.thread
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,60 +1,78 @@
|
|
1
1
|
module Commontator
|
2
2
|
class Comment < ActiveRecord::Base
|
3
3
|
belongs_to :creator, :polymorphic => true
|
4
|
-
belongs_to :
|
4
|
+
belongs_to :editor, :polymorphic => true
|
5
|
+
|
5
6
|
belongs_to :thread
|
6
|
-
|
7
|
+
|
7
8
|
has_one :commontable, :through => :thread
|
8
|
-
|
9
|
+
|
10
|
+
attr_accessible :body
|
11
|
+
|
9
12
|
validates_presence_of :creator, :on => :create
|
13
|
+
validates_presence_of :editor, :on => :update
|
14
|
+
|
10
15
|
validates_presence_of :thread
|
11
16
|
validates_presence_of :body
|
12
17
|
|
13
|
-
|
14
|
-
|
18
|
+
validates_uniqueness_of :body, :scope => [:creator_type, :creator_id, :thread_id],
|
19
|
+
:message => 'has already been posted'
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
15
23
|
cattr_accessor :acts_as_votable_initialized
|
16
|
-
|
24
|
+
|
25
|
+
public
|
26
|
+
|
17
27
|
def is_votable?
|
28
|
+
return true if acts_as_votable_initialized
|
18
29
|
return false unless self.class.respond_to?(:acts_as_votable)
|
19
|
-
self.class.acts_as_votable
|
30
|
+
self.class.acts_as_votable
|
20
31
|
self.class.acts_as_votable_initialized = true
|
21
32
|
end
|
22
|
-
|
33
|
+
|
34
|
+
def get_vote_by(user)
|
35
|
+
return nil unless is_votable?
|
36
|
+
votes.where(:voter_type => user.class.name, :voter_id => user.id).first
|
37
|
+
end
|
38
|
+
|
23
39
|
def is_modified?
|
24
|
-
|
40
|
+
!editor.nil?
|
25
41
|
end
|
26
|
-
|
42
|
+
|
27
43
|
def is_deleted?
|
28
44
|
!deleted_at.blank?
|
29
45
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
config = thread.config
|
33
|
-
(is_modified? ? 'Last modified on ' : \
|
34
|
-
"#{config.comment_create_verb_past.capitalize} on ") + \
|
35
|
-
updated_at.strftime(config.timestamp_format)
|
36
|
-
end
|
37
|
-
|
38
|
-
def delete(user = nil)
|
46
|
+
|
47
|
+
def delete_by(user)
|
39
48
|
return false if is_deleted?
|
40
49
|
self.deleted_at = Time.now
|
41
|
-
self.
|
42
|
-
self.save
|
50
|
+
self.editor = user
|
51
|
+
self.save
|
43
52
|
end
|
44
|
-
|
45
|
-
def
|
53
|
+
|
54
|
+
def undelete_by(user)
|
46
55
|
return false unless is_deleted?
|
47
56
|
self.deleted_at = nil
|
48
|
-
self.
|
57
|
+
self.editor = user
|
58
|
+
self.save
|
49
59
|
end
|
50
60
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
def timestamp
|
62
|
+
config = thread.config
|
63
|
+
"#{config.comment_create_verb_past.capitalize} on " + \
|
64
|
+
created_at.strftime(config.timestamp_format) + \
|
65
|
+
(is_modified? ? " | Last #{config.comment_edit_verb_past} on " + \
|
66
|
+
updated_at.strftime(config.timestamp_format) : '')
|
67
|
+
end
|
68
|
+
|
69
|
+
##################
|
70
|
+
# Access Control #
|
71
|
+
##################
|
72
|
+
|
55
73
|
def can_be_read_by?(user)
|
56
|
-
(thread.can_be_read_by?(user) &&
|
57
|
-
thread.config.deleted_comments_are_visible)) ||\
|
74
|
+
(thread.can_be_read_by?(user) && \
|
75
|
+
(!is_deleted? || thread.config.deleted_comments_are_visible)) ||\
|
58
76
|
thread.can_be_edited_by?(user)
|
59
77
|
end
|
60
78
|
|
@@ -72,20 +90,19 @@ module Commontator
|
|
72
90
|
def can_be_deleted_by?(user)
|
73
91
|
(!thread.is_closed? &&\
|
74
92
|
((user == creator && thread.config.can_delete_own_comments && \
|
75
|
-
thread.can_be_read_by?(user) && (!is_deleted? ||
|
93
|
+
thread.can_be_read_by?(user) && (!is_deleted? || editor == user)) &&\
|
76
94
|
(thread.comments.last == self || thread.config.can_delete_old_comments))) ||\
|
77
95
|
thread.can_be_edited_by?(user)
|
78
96
|
end
|
79
|
-
|
97
|
+
|
80
98
|
def can_be_voted_on?
|
81
|
-
is_votable? && !is_deleted? && thread.config.can_vote_on_comments
|
99
|
+
!thread.is_closed? && is_votable? && !is_deleted? && thread.config.can_vote_on_comments
|
82
100
|
end
|
83
101
|
|
84
102
|
def can_be_voted_on_by?(user)
|
85
|
-
can_be_voted_on? &&
|
86
|
-
thread.can_be_read_by?(user) && user != creator
|
103
|
+
can_be_voted_on? && thread.can_be_read_by?(user) && user != creator
|
87
104
|
end
|
88
105
|
end
|
89
|
-
|
106
|
+
|
90
107
|
CommentObserver.instance
|
91
108
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Commontator
|
2
|
+
class Comment < ActiveRecord::Base
|
3
|
+
belongs_to :creator, :polymorphic => true
|
4
|
+
belongs_to :editor, :polymorphic => true
|
5
|
+
|
6
|
+
belongs_to :thread
|
7
|
+
|
8
|
+
has_one :commontable, :through => :thread
|
9
|
+
|
10
|
+
attr_accessible :body
|
11
|
+
|
12
|
+
validates_presence_of :creator, :on => :create
|
13
|
+
validates_presence_of :editor, :on => :update
|
14
|
+
|
15
|
+
validates_presence_of :thread
|
16
|
+
validates_presence_of :body
|
17
|
+
|
18
|
+
validates_uniqueness_of :body, :scope => [:creator_type, :creator_id, :thread_id],
|
19
|
+
:message => 'has already been posted'
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
cattr_accessor :acts_as_votable_initialized
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
def is_votable?
|
28
|
+
return true if acts_as_votable_initialized
|
29
|
+
return false unless self.class.respond_to?(:acts_as_votable)
|
30
|
+
self.class.acts_as_votable
|
31
|
+
self.class.acts_as_votable_initialized = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_vote_by(user)
|
35
|
+
return nil unless is_votable?
|
36
|
+
votes.where(:voter_type => user.class.name, :voter_id => user.id).first
|
37
|
+
end
|
38
|
+
|
39
|
+
def is_modified?
|
40
|
+
!editor.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
def is_deleted?
|
44
|
+
!deleted_at.blank?
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete_by(user)
|
48
|
+
return false if is_deleted?
|
49
|
+
self.deleted_at = Time.now
|
50
|
+
self.editor = user
|
51
|
+
self.save
|
52
|
+
end
|
53
|
+
|
54
|
+
def undelete_by(user)
|
55
|
+
return false unless is_deleted?
|
56
|
+
self.deleted_at = nil
|
57
|
+
self.editor = user
|
58
|
+
self.save
|
59
|
+
end
|
60
|
+
|
61
|
+
def timestamp
|
62
|
+
config = thread.config
|
63
|
+
"#{config.comment_create_verb_past.capitalize} on ") + \
|
64
|
+
created_at.strftime(config.timestamp_format) + \
|
65
|
+
(is_modified? ? " | Last #{config.comment_edit_verb_past} on " + \
|
66
|
+
updated_at.strftime(config.timestamp_format) : '')
|
67
|
+
end
|
68
|
+
|
69
|
+
##################
|
70
|
+
# Access Control #
|
71
|
+
##################
|
72
|
+
|
73
|
+
def can_be_read_by?(user)
|
74
|
+
(thread.can_be_read_by?(user) && \
|
75
|
+
(!is_deleted? || thread.config.deleted_comments_are_visible)) ||\
|
76
|
+
thread.can_be_edited_by?(user)
|
77
|
+
end
|
78
|
+
|
79
|
+
def can_be_created_by?(user)
|
80
|
+
!thread.is_closed? && thread.can_be_read_by?(user) && user == creator
|
81
|
+
end
|
82
|
+
|
83
|
+
def can_be_edited_by?(user)
|
84
|
+
!thread.is_closed? && !is_deleted? &&\
|
85
|
+
((user == creator && thread.config.can_edit_own_comments && thread.can_be_read_by?(user)) ||\
|
86
|
+
(thread.can_be_edited_by?(user) && thread.config.admin_can_edit_comments)) &&\
|
87
|
+
(thread.comments.last == self || thread.config.can_edit_old_comments)
|
88
|
+
end
|
89
|
+
|
90
|
+
def can_be_deleted_by?(user)
|
91
|
+
(!thread.is_closed? &&\
|
92
|
+
((user == creator && thread.config.can_delete_own_comments && \
|
93
|
+
thread.can_be_read_by?(user) && (!is_deleted? || editor == user)) &&\
|
94
|
+
(thread.comments.last == self || thread.config.can_delete_old_comments))) ||\
|
95
|
+
thread.can_be_edited_by?(user)
|
96
|
+
end
|
97
|
+
|
98
|
+
def can_be_voted_on?
|
99
|
+
!thread.is_closed? && is_votable? && !is_deleted? && thread.config.can_vote_on_comments
|
100
|
+
end
|
101
|
+
|
102
|
+
def can_be_voted_on_by?(user)
|
103
|
+
can_be_voted_on? && thread.can_be_read_by?(user) && user != creator
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
CommentObserver.instance
|
108
|
+
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module Commontator
|
2
2
|
class Subscription < ActiveRecord::Base
|
3
3
|
belongs_to :subscriber, :polymorphic => true
|
4
|
+
|
4
5
|
belongs_to :thread
|
5
6
|
|
6
|
-
validates_presence_of :subscriber, :thread
|
7
|
-
validates_uniqueness_of :thread_id, :scope => [:subscriber_id, :subscriber_type]
|
8
|
-
|
9
7
|
attr_accessible :subscriber, :thread
|
10
|
-
|
8
|
+
|
9
|
+
validates_presence_of :subscriber, :thread
|
10
|
+
|
11
|
+
validates_uniqueness_of :thread_id, :scope => [:subscriber_type, :subscriber_id]
|
12
|
+
|
11
13
|
def mark_as_read
|
12
|
-
|
14
|
+
update_attribute(:unread, 0)
|
13
15
|
end
|
14
16
|
|
15
17
|
def add_unread
|
16
|
-
|
18
|
+
update_attribute(:unread, unread + 1)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Commontator
|
2
|
+
class Subscription < ActiveRecord::Base
|
3
|
+
belongs_to :subscriber, :polymorphic => true
|
4
|
+
|
5
|
+
belongs_to :thread
|
6
|
+
|
7
|
+
attr_accessible :subscriber, :thread
|
8
|
+
|
9
|
+
validates_presence_of :subscriber, :thread
|
10
|
+
|
11
|
+
validates_uniqueness_of :thread_id, :scope => [:subscriber_type, :subscriber_id]
|
12
|
+
|
13
|
+
def mark_as_read
|
14
|
+
self.update_attribute(:unread, 0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_unread
|
18
|
+
self.update_attribute(:unread, unread + 1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|