the_comments 0.9.0 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +398 -121
- data/app/assets/javascripts/the_comments.js.coffee +3 -3
- data/app/assets/javascripts/the_comments_manage.js.coffee +0 -2
- data/app/assets/stylesheets/the_comments.css.scss +6 -5
- data/app/controllers/concerns/the_comments_controller.rb +18 -16
- data/app/controllers/concerns/the_comments_user_agent_controller.rb +10 -12
- data/app/helpers/render_comments_tree_helper.rb +6 -5
- data/app/models/concerns/the_comments_base.rb +33 -28
- data/app/models/concerns/the_comments_commentable.rb +52 -40
- data/app/models/concerns/the_comments_states.rb +12 -12
- data/app/models/concerns/the_comments_user.rb +23 -16
- data/config/routes.rb +6 -6
- data/db/migrate/20130101010101_create_comments.rb +12 -3
- data/{the_comments.jpg → docs/the_comments.jpg} +0 -0
- data/docs/the_comments_view_1.gif +0 -0
- data/docs/the_comments_view_2.gif +0 -0
- data/docs/the_comments_view_3.gif +0 -0
- data/docs/the_comments_view_4.gif +0 -0
- data/docs/the_comments_view_5.gif +0 -0
- data/lib/generators/the_comments/templates/the_comments.rb +6 -3
- data/lib/generators/the_comments/views_generator.rb +3 -1
- data/lib/the_comments/config.rb +7 -4
- data/lib/the_comments/version.rb +1 -1
- data/lib/the_comments.rb +0 -1
- data/the_comments.gemspec +2 -1
- metadata +12 -18
@@ -44,20 +44,20 @@ $ ->
|
|
44
44
|
return false
|
45
45
|
|
46
46
|
$('.tolerance_time').val time_diff
|
47
|
-
button.
|
47
|
+
button.hide()
|
48
48
|
true
|
49
49
|
|
50
50
|
# AJAX ERROR
|
51
51
|
$(document).on 'ajax:error', comment_forms, (request, response, status) ->
|
52
52
|
form = $ @
|
53
|
-
$('input[type=submit]', form).
|
53
|
+
$('input[type=submit]', form).show()
|
54
54
|
error_msgs = error_text_builder(["Server Error: #{response.status}"])
|
55
55
|
comments_error_notifier(form, error_msgs)
|
56
56
|
|
57
57
|
# COMMENT FORMS => SUCCESS
|
58
58
|
$(document).on 'ajax:success', comment_forms, (request, response, status) ->
|
59
59
|
form = $ @
|
60
|
-
$('input[type=submit]', form).
|
60
|
+
$('input[type=submit]', form).show()
|
61
61
|
|
62
62
|
if typeof(response) is 'string'
|
63
63
|
anchor = $(response).find('.comment').attr('id')
|
@@ -4,12 +4,10 @@ $ ->
|
|
4
4
|
|
5
5
|
holder.on 'ajax:success', '.to_published', (request, response, status) ->
|
6
6
|
link = $ @
|
7
|
-
log link.parents('.item')
|
8
7
|
link.parents('.item').first().attr('class', 'item published')
|
9
8
|
|
10
9
|
holder.on 'ajax:success', '.to_draft', (request, response, status) ->
|
11
10
|
link = $ @
|
12
|
-
log link.parents('.item')
|
13
11
|
link.parents('.item').first().attr('class', 'item draft')
|
14
12
|
|
15
13
|
holder.on 'ajax:success', '.to_spam, .to_deleted', (request, response, status) ->
|
@@ -74,14 +74,14 @@
|
|
74
74
|
li{
|
75
75
|
.comment.draft{
|
76
76
|
border: 1px solid gray;
|
77
|
-
background:
|
77
|
+
background: #eff5f3;
|
78
78
|
padding: 10px;
|
79
79
|
}
|
80
80
|
}
|
81
81
|
|
82
82
|
.form_holder{ margin-left: 40px; }
|
83
83
|
|
84
|
-
.edit{
|
84
|
+
.edit, .delete{
|
85
85
|
margin-bottom: 3px;
|
86
86
|
text-align:center;
|
87
87
|
line-height: 130%;
|
@@ -89,6 +89,7 @@
|
|
89
89
|
color: white;
|
90
90
|
padding: 1px;
|
91
91
|
}
|
92
|
+
.delete{ background: gray; }
|
92
93
|
|
93
94
|
.comment{
|
94
95
|
overflow: hidden; zoom: 1;
|
@@ -105,12 +106,12 @@
|
|
105
106
|
padding: 3px;
|
106
107
|
}
|
107
108
|
.userbar{
|
108
|
-
background: #
|
109
|
+
background: #eff5f3;
|
109
110
|
border-radius: 3px;
|
110
111
|
padding-left: 7px;
|
111
112
|
}
|
112
113
|
&.draft{
|
113
|
-
.userbar{ background: #
|
114
|
+
.userbar{ background: #ffa768; }
|
114
115
|
.to_draft{ display: none; }
|
115
116
|
}
|
116
117
|
&.published{
|
@@ -143,7 +144,7 @@
|
|
143
144
|
border-radius: 3px;
|
144
145
|
padding: 5px;
|
145
146
|
}
|
146
|
-
&.highlighted{ border: 1px dashed #ff6633; }
|
147
|
+
&.highlighted{ border: 1px dashed #ff6633 !important; }
|
147
148
|
|
148
149
|
}
|
149
150
|
|
@@ -1,31 +1,24 @@
|
|
1
1
|
module TheCommentsController
|
2
2
|
COMMENTS_COOKIES_TOKEN = 'JustTheCommentsCookies'
|
3
3
|
|
4
|
-
# View token for
|
4
|
+
# Cookies and View token for spam protection
|
5
5
|
#
|
6
|
-
# class
|
6
|
+
# class ApplicationController < ActionController::Base
|
7
7
|
# include TheCommentsController::ViewToken
|
8
8
|
# end
|
9
9
|
module ViewToken
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
included { before_action :set_the_comments_cookies }
|
12
|
+
|
10
13
|
def comments_view_token
|
11
|
-
cookies[:comments_view_token] = { :value => SecureRandom.hex, :expires => 7.days.from_now } unless cookies[:comments_view_token]
|
12
14
|
cookies[:comments_view_token]
|
13
15
|
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Cookies for spam protection
|
17
|
-
#
|
18
|
-
# class ApplicationController < ActionController::Base
|
19
|
-
# include TheCommentsController::Cookies
|
20
|
-
# end
|
21
|
-
module Cookies
|
22
|
-
extend ActiveSupport::Concern
|
23
|
-
included { before_action :set_the_comments_cookies }
|
24
16
|
|
25
17
|
private
|
26
18
|
|
27
19
|
def set_the_comments_cookies
|
28
|
-
cookies[:the_comment_cookies] = { :
|
20
|
+
cookies[:the_comment_cookies] = { value: TheCommentsController::COMMENTS_COOKIES_TOKEN, expires: 1.year.from_now }
|
21
|
+
cookies[:comments_view_token] = { value: SecureRandom.hex, expires: 7.days.from_now } unless cookies[:comments_view_token]
|
29
22
|
end
|
30
23
|
end
|
31
24
|
|
@@ -72,10 +65,15 @@ module TheCommentsController
|
|
72
65
|
end
|
73
66
|
|
74
67
|
def my
|
75
|
-
@comments = current_user.
|
68
|
+
@comments = current_user.my_comments.order('created_at DESC').page(params[:page])
|
76
69
|
render template: 'the_comments/index'
|
77
70
|
end
|
78
71
|
|
72
|
+
def new
|
73
|
+
@comments = current_user.my_comments.with_state(:draft).order('created_at DESC').page(params[:page])
|
74
|
+
render template: 'the_comments/manage'
|
75
|
+
end
|
76
|
+
|
79
77
|
def incoming
|
80
78
|
@comments = current_user.comcoms.with_state(:draft, :published).order('created_at DESC').page(params[:page])
|
81
79
|
render template: 'the_comments/manage'
|
@@ -86,7 +84,9 @@ module TheCommentsController
|
|
86
84
|
render template: 'the_comments/manage'
|
87
85
|
end
|
88
86
|
|
89
|
-
#
|
87
|
+
# BASE METHODS
|
88
|
+
|
89
|
+
# Public methods
|
90
90
|
|
91
91
|
def update
|
92
92
|
comment = Comment.where(id: params[:id]).first
|
@@ -103,6 +103,8 @@ module TheCommentsController
|
|
103
103
|
render json: { errors: @comment.errors.full_messages }
|
104
104
|
end
|
105
105
|
|
106
|
+
# Protected methods
|
107
|
+
|
106
108
|
def to_published
|
107
109
|
Comment.where(id: params[:id]).first.to_published
|
108
110
|
render nothing: :true
|
@@ -1,17 +1,15 @@
|
|
1
1
|
module TheCommentsUserAgentController
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
UserAgentBlackList.order('count DESC').page(params[:page])
|
10
|
-
end
|
2
|
+
# extend ActiveSupport::Concern
|
3
|
+
# included do; end
|
4
|
+
def index
|
5
|
+
@ip_black_lists = if params[:ip]
|
6
|
+
UserAgentBlackList.where(ip: params[:ip])
|
7
|
+
else
|
8
|
+
UserAgentBlackList.order('count DESC').page(params[:page])
|
11
9
|
end
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def to_state
|
13
|
+
return render text: UserAgentBlackList.where(id: params[:user_agent_black_list_id]).first.update!(state: params[:state])
|
16
14
|
end
|
17
15
|
end
|
@@ -39,10 +39,8 @@ module RenderCommentsTreeHelper
|
|
39
39
|
|
40
40
|
if @comment.draft?
|
41
41
|
draft_comment
|
42
|
-
|
42
|
+
else @comment.published?
|
43
43
|
published_comment
|
44
|
-
else
|
45
|
-
deleted_comment
|
46
44
|
end
|
47
45
|
end
|
48
46
|
|
@@ -89,10 +87,13 @@ module RenderCommentsTreeHelper
|
|
89
87
|
"<div class='userbar'>#{ title } #{ anchor }</div>"
|
90
88
|
end
|
91
89
|
|
92
|
-
def moderator_controls
|
90
|
+
def moderator_controls
|
91
|
+
t = ''
|
93
92
|
if moderator?
|
94
|
-
h.link_to
|
93
|
+
t += h.link_to(t('the_comments.edit'), h.edit_comment_url(@comment), class: :edit)
|
94
|
+
t += h.link_to(t('the_comments.to_deleted'), h.to_trash_comment_url(@comment), class: :delete, method: :delete, remote: true, confirm: t('the_comments.delete_confirm'))
|
95
95
|
end
|
96
|
+
t
|
96
97
|
end
|
97
98
|
|
98
99
|
def reply
|
@@ -23,42 +23,47 @@ module TheCommentsBase
|
|
23
23
|
belongs_to :commentable, polymorphic: true
|
24
24
|
|
25
25
|
# callbacks
|
26
|
-
before_create :define_holder, :define_anchor, :denormalize_commentable
|
26
|
+
before_create :define_holder, :define_default_state, :define_anchor, :denormalize_commentable
|
27
27
|
after_create :update_cache_counters
|
28
28
|
before_save :prepare_content
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
def avatar_url
|
32
|
+
src = id.to_s
|
33
|
+
src = title unless title.blank?
|
34
|
+
src = contacts if !contacts.blank? && /@/ =~ contacts
|
35
|
+
hash = Digest::MD5.hexdigest(src)
|
36
|
+
"http://www.gravatar.com/avatar/#{hash}?s=40&d=identicon"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
37
40
|
|
38
|
-
|
41
|
+
def define_anchor
|
42
|
+
self.anchor = SecureRandom.hex[0..5]
|
43
|
+
end
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
def define_holder
|
46
|
+
c = self.commentable
|
47
|
+
self.holder = c.is_a?(User) ? c : c.try(:user)
|
48
|
+
end
|
43
49
|
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
def define_default_state
|
51
|
+
self.state = TheComments.config.default_owner_state if user && user == holder
|
52
|
+
end
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
54
|
+
def denormalize_commentable
|
55
|
+
self.commentable_title = self.commentable.try :commentable_title
|
56
|
+
self.commentable_url = self.commentable.try :commentable_url
|
57
|
+
self.commentable_state = self.commentable.try :state
|
58
|
+
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
60
|
+
def prepare_content
|
61
|
+
self.content = self.raw_content
|
62
|
+
end
|
57
63
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
64
|
+
def update_cache_counters
|
65
|
+
user.try :recalculate_my_comments_counter!
|
66
|
+
commentable.try :increment!, :draft_comments_count
|
67
|
+
holder.try :increment!, :draft_comcoms_count
|
63
68
|
end
|
64
69
|
end
|
@@ -3,48 +3,60 @@ module TheCommentsCommentable
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
has_many :comments, as: :commentable
|
6
|
-
|
7
|
-
#
|
8
|
-
# *define_denormalize_flags* - should be placed before
|
9
|
-
# title or url builder filters
|
6
|
+
|
7
|
+
# *define_denormalize_flags* - should be placed before title or url builder filters
|
10
8
|
before_validation :define_denormalize_flags
|
11
9
|
after_save :denormalize_for_comments
|
10
|
+
end
|
11
|
+
|
12
|
+
def commentable_title
|
13
|
+
try(:title) || TheComments.config.default_title
|
14
|
+
end
|
15
|
+
|
16
|
+
def commentable_url
|
17
|
+
# /pages/1
|
18
|
+
['', self.class.to_s.tableize, self.to_param].join('/')
|
19
|
+
end
|
20
|
+
|
21
|
+
def commentable_state
|
22
|
+
# 'draft'
|
23
|
+
try(:state)
|
24
|
+
end
|
25
|
+
|
26
|
+
def comments_sum
|
27
|
+
published_comments_count + draft_comments_count
|
28
|
+
end
|
29
|
+
|
30
|
+
def recalculate_comments_counters!
|
31
|
+
self.draft_comments_count = comments.with_state(:draft).count
|
32
|
+
self.published_comments_count = comments.with_state(:published).count
|
33
|
+
self.deleted_comments_count = comments.with_state(:deleted).count
|
34
|
+
save
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def define_denormalize_flags
|
40
|
+
@trackable_commentable_title = commentable_title
|
41
|
+
@trackable_commentable_state = commentable_state
|
42
|
+
@trackable_commentable_url = commentable_url
|
43
|
+
end
|
44
|
+
|
45
|
+
# Can you make it better? I don't know how.
|
46
|
+
def denormalization_fields_changed?
|
47
|
+
@title_field_changed = @trackable_commentable_title != commentable_title
|
48
|
+
@state_field_changed = @trackable_commentable_state != commentable_state
|
49
|
+
@url_field_changed = @trackable_commentable_url != commentable_url
|
50
|
+
@title_field_changed || @url_field_changed || @state_field_changed
|
51
|
+
end
|
12
52
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def comments_sum
|
23
|
-
published_comments_count + draft_comments_count
|
24
|
-
end
|
25
|
-
|
26
|
-
def recalculate_comments_counters
|
27
|
-
self.draft_comments_count = comments.with_state(:draft).count
|
28
|
-
self.published_comments_count = comments.with_state(:published).count
|
29
|
-
self.deleted_comments_count = comments.with_state(:deleted).count
|
30
|
-
save
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def define_denormalize_flags
|
36
|
-
@_commentable_title = commentable_title
|
37
|
-
@_commentable_url = commentable_url
|
38
|
-
end
|
39
|
-
|
40
|
-
def denormalize_for_comments
|
41
|
-
title_changed = @_commentable_title != commentable_title
|
42
|
-
url_changed = @_commentable_url != commentable_url
|
43
|
-
cstate = try(:state_changed?) ? { commentable_state: state } : {}
|
44
|
-
|
45
|
-
if title_changed || url_changed || !cstate.blank?
|
46
|
-
comments.update_all({ commentable_title: commentable_title, commentable_url: commentable_url}.merge(cstate))
|
47
|
-
end
|
48
|
-
end
|
53
|
+
def denormalize_for_comments
|
54
|
+
if denormalization_fields_changed?
|
55
|
+
comments.update_all({
|
56
|
+
commentable_title: commentable_title,
|
57
|
+
commentable_state: commentable_state,
|
58
|
+
commentable_url: commentable_url
|
59
|
+
})
|
60
|
+
end
|
49
61
|
end
|
50
62
|
end
|
@@ -3,7 +3,7 @@ module TheCommentsStates
|
|
3
3
|
|
4
4
|
included do
|
5
5
|
# :draft | :published | :deleted
|
6
|
-
state_machine :state, :initial =>
|
6
|
+
state_machine :state, :initial => TheComments.config.default_state do
|
7
7
|
|
8
8
|
# events
|
9
9
|
event :to_draft do
|
@@ -31,33 +31,33 @@ module TheCommentsStates
|
|
31
31
|
from = transition.from_name
|
32
32
|
to = transition.to_name
|
33
33
|
|
34
|
-
@holder.try :increment!,
|
35
|
-
@holder.try :decrement!,
|
34
|
+
@holder.try :increment!, "#{to}_comcoms_count"
|
35
|
+
@holder.try :decrement!, "#{from}_comcoms_count"
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
obj.try :decrement!, "#{from}_comments_count"
|
40
|
-
end
|
37
|
+
@commentable.try :increment!, "#{to}_comments_count"
|
38
|
+
@commentable.try :decrement!, "#{from}_comments_count"
|
41
39
|
end
|
42
40
|
|
43
41
|
# to deleted (cascade like query)
|
44
42
|
after_transition [:draft, :published] => :deleted do |comment|
|
45
43
|
ids = comment.self_and_descendants.map(&:id)
|
46
44
|
Comment.where(id: ids).update_all(state: :deleted)
|
47
|
-
|
45
|
+
@owner.try :recalculate_my_comments_counter!
|
46
|
+
@holder.try :recalculate_comcoms_counters!
|
47
|
+
@commentable.try :recalculate_comments_counters!
|
48
48
|
end
|
49
49
|
|
50
50
|
# from deleted
|
51
51
|
after_transition :deleted => [:draft, :published] do |comment, transition|
|
52
52
|
to = transition.to_name
|
53
53
|
|
54
|
+
@owner.try :recalculate_my_comments_counter!
|
55
|
+
|
54
56
|
@holder.try :decrement!, :deleted_comcoms_count
|
55
57
|
@holder.try :increment!, "#{to}_comcoms_count"
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
obj.try :increment!, "#{to}_comments_count"
|
60
|
-
end
|
59
|
+
@commentable.try :decrement!, :deleted_comments_count
|
60
|
+
@commentable.try :increment!, "#{to}_comments_count"
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|