the_comments 0.9.0 → 0.9.9

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/README.md CHANGED
@@ -1,157 +1,202 @@
1
- # TheComments 0.9.0
1
+ # TheComments 1.0.0
2
+
3
+ TheComments - just comment system for my Ruby on Rails 4 projects
4
+
5
+ P.S: and for me it's best prototype of comment system for Rails 4
6
+
7
+ ## Keywords
8
+
9
+ Comments for Rails 4, Comments with threading, Nested Comments, Polymorphic comments, Acts as commentable, Comment functionality, Comments, Threading, Rails 4, Comments with moderation, I hate captcha for comments!
10
+
11
+ ## Screenshots
12
+
13
+ **click to zoom**
14
+
15
+ <table>
16
+ <tr>
17
+ <td width="20%">Guest view</td>
18
+ <td width="20%">Admin view</td>
19
+ <td width="20%">Edit</td>
20
+ <td width="20%">Cache counters & User Cabinet</td>
21
+ <td width="20%">Recent comments & Denormalization</td>
22
+ </tr>
23
+ <tr>
24
+ <td width="20%"><img width="100%" height="100%" src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_2.gif" alt="the_comments"></td>
25
+ <td width="20%"><img width="100%" height="100%" src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_1.gif" alt="the_comments"></td>
26
+ <td width="20%"><img width="100%" height="100%" src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_4.gif" alt="the_comments"></td>
27
+ <td width="20%"><img width="100%" height="100%" src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_3.gif" alt="the_comments"></td>
28
+ <td width="20%"><img width="100%" height="100%" src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_5.gif" alt="the_comments"></td>
29
+ </tr>
30
+ </table>
31
+
32
+ ### Main features
33
+
34
+ * Threaded comments
35
+ * Tree rendering via [TheSortableTree](https://github.com/the-teacher/the_sortable_tree)
36
+ * [Denormalization](#denormalization) for Recent comments
37
+ * Usefull cache counters
38
+ * Basic AntiSpam system
39
+ * Online Support via skype: **ilya.killich**
40
+
41
+ ### Intro (understanding)
42
+
43
+ * [My hopes about comments system](#my-hopes-about-comments-system)
44
+ * [What's wrong with other gems?](#whats-wrong-with-other-gems)
45
+ * [Comments, Posted comments & ComComs](#comments-posted-comments-comcoms)
46
+ * [Denormalization and Recent comments](#denormalization)
47
+ * [Recent comments building](#recent-comments-building)
48
+ * [AntiSpam system](#antispam-system)
49
+ * [Customization](#customization)
50
+ * [User methods](#user-methods)
51
+ * [Commentable methods](#commentable-methods)
52
+ * [Online Support](#online-support)
53
+ * [About author](#about-author)
2
54
 
3
- TheComments - probably, best solution for comments for Ruby on Rails.
55
+ ## Installation
4
56
 
5
- ### What's wrong with other gems?
57
+ This gem has many steps to install. Be careful when installing and keep calm.
6
58
 
7
- Just look at [Ruby-Toolbox](https://www.ruby-toolbox.com/categories/rails_comments). What we can see?
59
+ Just follow an installation instruction step by step and everything will be fine!
8
60
 
9
- * [Acts as commentable with threading](https://github.com/elight/acts_as_commentable_with_threading) - so, guys, where is the render helper for the tree? There is no helper! Should I make render helper for tree by myself? Nooooo!!! I'm so sorry, but I can't use this gem.
10
- * [acts_as_commentable](https://github.com/jackdempsey/acts_as_commentable) - so, I can see code for models. But I can't see code for controllers and views. Unfortunately, there is no threading. It's not enough for me.
11
- * [opinio](https://github.com/Draiken/opinio) - looks better, but there is no threading. I want to have more!
12
- * [has_threaded_comments](https://github.com/aarongough/has_threaded_comments) - Nice work! Nice gem! Models, controllers, views, view helper for tree rendering! **But**, last activity 2 years ago, I need few features, I think - I can make it better.
61
+ **Installation process consist of 4 main steps:**
13
62
 
14
- ### In sum
63
+ * [Gem Installation](#gem-installation)
64
+ * [Code Installation](#code-installation)
65
+ * [Tuning](#tuning)
66
+ * [Using](#using)
15
67
 
16
- ![TheComments](https://raw.github.com/open-cook/the_comments/master/the_comments.jpg)
68
+ ## Gem Installation
17
69
 
18
- ### My hopes about comments system
19
-
20
- * Open comments for everybody (by default). *I hate user registration*
21
- * Moderation for comments and simple Admin UI
22
- * Spam traps instead Captcha. *I hate Captcha*
23
- * Blacklists for IP and UserAgent
24
- * Comment counters for commentable objects and User
25
- * Denormalization for fast and Request-free comment list building
26
- * Ready for external content filters ( **sanitize**, **RedCloth**, **Markdown**)
27
- * Ready for Rails4 (and Rails::Engine)
28
- * Delete without destroy
29
-
30
- ### Requires
70
+ **1)** change your Gemfile
31
71
 
32
72
  ```ruby
73
+ # I use *awesome_nested_set* gem to provide threading for comments
74
+ # But you can use other nested set gem, for example:
75
+ # gem 'nested_set' (github.com/skyeagle/nested_set)
33
76
  gem 'awesome_nested_set'
34
- gem 'the_sortable_tree'
35
- gem 'state_machine'
77
+
78
+ # I use haml for default views
79
+ # You can remove this dependancy,
80
+ # but you will should rewrite default views with your template engine
81
+ gem 'haml'
82
+
83
+ # finally, this gem
84
+ gem 'the_comments'
36
85
  ```
37
86
 
38
- ### Anti Spam system
87
+ **2)** bundle
39
88
 
40
- User agent must have:
89
+ **3)** Copy migration file into application, <b>OPEN FILE AND FOLLOW AN INSTRUCTION</b>.
41
90
 
42
- * Cookies support
43
- * JavaScript and Ajax support
91
+ ```ruby
92
+ bundle exec rake the_comments_engine:install:migrations
93
+ ```
44
94
 
45
- _Usually spambot not support Cookies and JavaScript_
95
+ **4)** run migration
46
96
 
47
- Comment form has:
97
+ ```ruby
98
+ bundle exec rake db:migrate
99
+ ```
48
100
 
49
- * fake (hidden) fields
101
+ ## Code Installation
50
102
 
51
- _Usually spam bot puts data in fake inputs_
103
+ **1)** Assets
52
104
 
53
- Trap via time:
105
+ *app/assets/javascripts/application.js*
54
106
 
55
- * User should be few seconds on page, before comment sending (by default 5 sec)
107
+ ```js
108
+ //= require the_comments
109
+ //= require the_comments_manage
110
+ ```
56
111
 
57
- _Usually spam bots works faster, than human. We can try to use this feature of behavior_
112
+ *app/assets/stylesheets/application.css*
58
113
 
59
- ## Installation
114
+ ```css
115
+ *= require the_comments
116
+ ```
117
+
118
+ **2)** Change your ApplicationController
60
119
 
61
120
  ```ruby
62
- gem 'the_comments'
121
+ class ApplicationController < ActionController::Base
122
+ include TheCommentsController::ViewToken
123
+ end
63
124
  ```
64
125
 
65
- **bundle**
126
+ **3)** Run generator, <b>OPEN EACH OF CREATED FILES AND FOLLOW INSTRUCTIONS</b>.
66
127
 
67
128
  ```ruby
68
- bundle exec rails g the_comment install
129
+ bundle exec rails g the_comments install
69
130
  ```
70
131
 
71
- ### Assets
132
+ *List of created files:*
72
133
 
73
- **app/assets/javascripts/application.js**
134
+ ```ruby
135
+ config/initializers/the_comments.rb
74
136
 
75
- ```js
76
- //= require the_comments
137
+ app/controllers/comments_controller.rb
138
+ app/controllers/ip_black_lists_controller.rb
139
+ app/controllers/user_agent_black_lists_controller.rb
77
140
  ```
78
141
 
79
- **app/assets/stylesheets/application.css**
142
+ **4)** Copy view files into your application
80
143
 
81
- ```css
82
- /*
83
- *= require the_comments
84
- */
144
+ ```ruby
145
+ bundle exec rails g the_comments:views views
85
146
  ```
86
147
 
148
+ *List of created directories with view files:*
149
+
150
+ ```ruby
151
+ app/views/the_comments/*.haml
152
+ app/views/ip_black_lists/*.haml
153
+ app/views/user_agent_black_lists/*.haml
154
+ ```
155
+
156
+ ## Tuning
157
+
87
158
  ### User Model
88
159
 
89
160
  ```ruby
90
161
  class User < ActiveRecord::Base
162
+ include TheCommentsUser
163
+
91
164
  # Your implementation of role policy
92
165
  def admin?
93
166
  self == User.first
94
167
  end
95
168
 
96
- # include TheComments methods
97
- include TheCommentsUser
98
-
99
- # denormalization for commentable objects
100
- def commentable_title
101
- login
102
- end
103
-
104
- def commentable_url
105
- [class.to_s.tableize, login].join('/')
106
- end
107
-
108
169
  # Comments moderator checking (simple example)
109
170
  # Usually comment's holder should be moderator
110
171
  def comment_moderator? comment
111
172
  admin? || id == comment.holder_id
112
173
  end
113
-
114
174
  end
115
175
  ```
116
176
 
117
- **User#coments** - comments. Set of all created comments
118
-
119
- ```ruby
120
- User.first.comments
121
- # => Array of comments, where User is creator (owner)
122
- ```
123
-
124
- **User#comcoms** - commentable comments. Set of all comments of all owned commentable objects of this user.
125
-
126
- ```ruby
127
- User.first.comcoms
128
- # => Array of all comments of all owned commentable objects, where User is holder
129
- # Usually comment's holder should be moderator of this comments
130
- # because this user should maintain cleaness of his commentable objects
131
- ```
132
-
133
- **Attention!** You should be sure that you understand who is owner, and who is holder of comments!
134
-
135
- ### Commentable Model (Page, Blog, Article, User ...)
136
-
137
- **Attention!** User model can be commentable object also.
177
+ ### Any Commentable Model (Page, Blog, Article, User(!) ...)
138
178
 
139
179
  ```ruby
140
180
  class Blog < ActiveRecord::Base
141
- # include TheComments methods
142
181
  include TheCommentsCommentable
143
182
 
144
- # (!) Every commentable Model must have next 2 methods
145
- # denormalization for commentable objects
146
183
  def commentable_title
147
- # "My first blog post"
148
- title
184
+ # by default: try(:title) || 'Undefined title'
185
+ # for example: "My first blog post"
186
+ blog_post_name
149
187
  end
150
188
 
151
189
  def commentable_url
152
- # blogs/1-my-first-blog-post
190
+ # by default: ['', self.class.to_s.tableize, self.to_param].join('/')
191
+ # for example: "blogs/1-my-first-blog-post"
153
192
  [self.class.to_s.tableize, slug_id].join('/')
154
193
  end
194
+
195
+ def commentable_state
196
+ # by default: try(:state)
197
+ # for example: "draft"
198
+ self.ban_flag == true ? :banned : :published
199
+ end
155
200
  end
156
201
  ```
157
202
 
@@ -159,7 +204,6 @@ end
159
204
 
160
205
  ```ruby
161
206
  class Comment < ActiveRecord::Base
162
- # include TheComments methods
163
207
  include TheCommentsBase
164
208
 
165
209
  # Define comment's avatar url
@@ -186,27 +230,12 @@ class Comment < ActiveRecord::Base
186
230
  end
187
231
  ```
188
232
 
189
- ### IP, User Agent black lists
190
-
191
- Models must looks like this:
192
-
193
- ```ruby
194
- class IpBlackList < ActiveRecord::Base
195
- include TheCommentsBlackUserAgent
196
- end
197
-
198
- class UserAgentBlackList < ActiveRecord::Base
199
- include TheCommentsBlackIp
200
- end
201
- ```
233
+ ## Using
202
234
 
203
235
  ### Commentable controller
204
236
 
205
237
  ```ruby
206
238
  class BlogsController < ApplicationController
207
- include TheCommentsController::Cookies
208
- include TheCommentsController::ViewToken
209
-
210
239
  def show
211
240
  @blog = Blog.where(id: params[:id]).with_states(:published).first
212
241
  @comments = @blog.comments.with_state([:draft, :published]).nested_set
@@ -220,29 +249,277 @@ end
220
249
  %h1= @blog.title
221
250
  %p= @blog.content
222
251
 
223
- = render partial: 'comments/tree', locals: { comments_tree: @comments, commentable: @blog }
252
+ = render partial: 'the_comments/tree', locals: { commentable: @blog, comments_tree: @comments }
224
253
  ```
225
254
 
226
- ## Configuration
255
+ ## Understanding
256
+
257
+ ### My hopes about comments system
258
+
259
+ * Open comments for everybody (by default). *I hate user registration*
260
+ * Polymorphic comments for any AR Model
261
+ * Threading for comments (can be plain comments list)
262
+ * Cache counters for commentable objects and User
263
+ * Moderation for comments and simple Admin UI
264
+ * Spam traps instead Captcha. *I hate Captcha*
265
+ * Blacklists for IP and UserAgent
266
+ * Denormalization for fast and Request-free Recent comments building
267
+ * Ready for external content filters (<b>sanitize</b>, <b>RedCloth</b>, <b>Markdown</b>)
268
+ * Highlighting and Jumping to comment via anchor
269
+ * Ready for Rails4 (and Rails::Engine)
270
+ * Ready for JQuery 1.9+
271
+ * Delete without destroy
272
+
273
+ ### What's wrong with other gems?
274
+
275
+ Just look at [Ruby-Toolbox](https://www.ruby-toolbox.com/categories/rails_comments). What we can see?
276
+
277
+ * [Acts as commentable with threading](https://github.com/elight/acts_as_commentable_with_threading) - so, guys, where is the render helper for the tree? There is no helper! Should I make render helper for tree by myself? Nooooo!!! I'm so sorry, but I can't use this gem.
278
+ * [acts_as_commentable](https://github.com/jackdempsey/acts_as_commentable) - so, I can see code for models. But I can't see code for controllers and views. Unfortunately, there is no threading. It's not enough for me.
279
+ * [opinio](https://github.com/Draiken/opinio) - looks better, but there is no threading. I want to have more!
280
+ * [has_threaded_comments](https://github.com/aarongough/has_threaded_comments) - Nice work! Nice gem! Models, controllers, views, view helper for tree rendering! **But**, last activity 2 years ago, I need few features, I think - I can make it better.
281
+
282
+ ![TheComments](https://raw.github.com/open-cook/the_comments/master/docs/the_comments.jpg)
227
283
 
228
- **config/initializers/the_comments.rb**
284
+ ## Comments, Posted comments, ComComs
285
+
286
+ ### Posted comments
287
+
288
+ **@user.posted_comments** (has_many)
289
+
290
+ Set of comments, where current user is owner (creator).
229
291
 
230
292
  ```ruby
231
- TheComments.configure do |config|
232
- config.max_reply_depth = 3 # 3 by default
233
- config.tolerance_time = 15 # 5 (sec) by default
234
- config.empty_inputs = [:email, :message, :commentBody] # [:message] by default
235
- end
293
+ @my_comments = @user.posted_comments # => [comment, comment, ...]
294
+
295
+ @comment = @my_comments.first
296
+ @user.id == @comment.user_id # => true
236
297
  ```
237
298
 
238
- * **max_reply_depth** - comments tree nesting by default
239
- * **tolerance_time** - how many seconds user should spend on page, before comment send
240
- * **empty_inputs** - names of hidden (via css) fields for spam detecting
299
+ ### Comments
300
+
301
+ **@commentable.comments** (has_many)
302
+
303
+ Set of comments for this commentable object
304
+
305
+ ```ruby
306
+ @comments = @blog.comments # => [comment, comment, ...]
307
+
308
+ @comment = @comments.first
309
+ @comment.commentable_id == @blog.id # => true
310
+ @comment.commentable_type == 'Blog' # => true
311
+ ```
312
+
313
+ <b>(!) Attention:</b> User Model can be commentable object too!
314
+
315
+ ```ruby
316
+ @comments = @user.comments # => [comment, comment, ...]
317
+
318
+ @comment = @comments.first
319
+ @comment.commentable_id == @user.id # => true
320
+ @comment.commentable_type == 'User' # => true
321
+ ```
322
+
323
+ ### ComComs (COMments of COMmentable objects)
324
+
325
+ **@user.comcoms** (has_many)
326
+
327
+ Set of All <b>COM</b>ments of All <b>COM</b>mentable objects of this User
328
+
329
+ ```ruby
330
+ @comcoms = @user.comcoms # => [comment, comment, ...]
331
+
332
+ @comcom = @comcoms.first
333
+ @user.id == @comcom.holder_id # => true
334
+ ```
335
+
336
+ **Comment#holder_id** should not be empty. Because we should to know, who is moderator of this comment.
337
+
338
+ ```ruby
339
+ @user.id == @comment.holder_id # => true
340
+ # => This user should be MODERATOR for this comment
341
+ ```
342
+
343
+ ## Denormalization
344
+
345
+ For building of Recent comments list (for polymorphic relationship) we need to have many additional requests to database. It's classic problem of polymorphic comments.
346
+
347
+ I use denormalization of commentable objects for solve of this problem.
348
+
349
+ My practice shows - We need 3 denormalized fields into comment for (request-free) building of recent comments list:
350
+
351
+ <img src="https://raw.github.com/open-cook/the_comments/master/docs/the_comments_view_5.gif" alt="the_comments">
352
+
353
+ * **Comment#commentable_title** - for example: "My first post about Ruby On Rails"
354
+ * **Comment#commentable_url** - for example: "/posts/1-my-first-post-about-ruby-on-rails"
355
+ * **Comment#commentable_state** - for example: "draft"
356
+
357
+ That is why any **Commentable Model should have few methods** to provide denormalization for Comments.
358
+
359
+ ## Recent comments building
360
+
361
+ Denormalization makes, building of Recent comments (for polymorphic relationship) is very easy!
362
+
363
+ Controller:
364
+
365
+ ```ruby
366
+ @comments = Comment.with_state(:published)
367
+ .where(commentable_state: [:published])
368
+ .order('created_at DESC')
369
+ .page(params[:page])
370
+ ```
371
+
372
+ View:
373
+
374
+ ```ruby
375
+ - @comments.each do |comment|
376
+ %div
377
+ %p= comment.commentable_title
378
+ %p= link_to comment.commentable_title, comment.commentable_url
379
+ %p= comment.content
380
+ ```
381
+
382
+ ### AntiSpam system
383
+
384
+ **1) Moderation**
385
+
386
+ **2) User agent must have:**
387
+
388
+ * Cookies support
389
+ * JavaScript and Ajax support
390
+
391
+ _Usually spambots not support Cookies and JavaScript_
392
+
393
+ **3) Comment form mast have:**
394
+
395
+ * fake (hidden via css) fields
396
+
397
+ _Usually spambots puts data in fake inputs_
398
+
399
+ **4) Trap via time:**
400
+
401
+ * User should be few seconds on page, before comment sending (by default 5 sec)
402
+
403
+ _Usually spambots works faster, than human. We can try to use this feature of behavior_
404
+
405
+ **5) IP and User Agent blacklists**
406
+
407
+
408
+ ### Strong dependencies of gem
409
+
410
+ ```ruby
411
+ gem 'the_sortable_tree'
412
+ gem 'state_machine'
413
+ ```
414
+
415
+ * **the_sortable_tree** - render helper for nested set
416
+ * **state_machine** - states for moderation and callbacks for recalculating of counters when state of comment was changed
417
+
418
+ ## Customization
419
+
420
+ You can use **generators** for copy files into your Application. After that you can customize almost everything
421
+
422
+ Generators list:
423
+
424
+ ```ruby
425
+ bundle exec rails g the_comments --help
426
+ ```
427
+
428
+ Copy View files for customization:
429
+
430
+ ```ruby
431
+ bundle exec rails g the_comments:views assets
432
+ bundle exec rails g the_comments:views views
433
+ ```
434
+
435
+ Copy Helper file for tree customization:
436
+
437
+ For more info read [TheSortableTree doc](https://github.com/the-teacher/the_sortable_tree)
438
+
439
+ ```ruby
440
+ bundle exec rails g the_comments:views helper
441
+ ```
442
+ ### User methods
443
+
444
+ * @user.<b>posted_comments</b> (all states)
445
+ * @user.<b>my_comments</b> (draft, published)
446
+ * @user.<b>my_comments_count</b>
447
+
448
+ Cache counters methods
449
+
450
+ * @user.<b>recalculate_my_comments_counter!</b>
451
+ * @user.<b>recalculate_comcoms_counters!</b>
452
+
453
+ Comments methods
454
+
455
+ * @user.<b>comments</b>
456
+ * @user.<b>comments_sum</b>
457
+ * @user.<b>draft_comments_count</b>
458
+ * @user.<b>published_comments_count</b>
459
+ * @user.<b>deleted_comments_count</b>
460
+
461
+ Comcoms methods
462
+
463
+ * @user.<b>comcoms</b>
464
+ * @user.<b>comcoms_sum</b>
465
+ * @user.<b>draft_comcoms_count</b>
466
+ * @user.<b>published_comcoms_count</b>
467
+ * @user.<b>deleted_comcoms_count</b>
468
+
469
+ ### Commentable methods
470
+
471
+ * @post.<b>comments</b>
472
+ * @post.<b>draft_comments_count</b>
473
+ * @post.<b>published_comments_count</b>
474
+ * @post.<b>deleted_comments_count</b>
475
+ * @post.<b>comments_sum</b> (draft + published)
476
+ * @post.<b>recalculate_comments_counters!</b>
477
+
478
+ Denornalization methods
479
+
480
+ * @post.<b>commentable_title</b>
481
+ * @post.<b>commentable_url</b>
482
+ * @post.<b>commentable_state</b>
483
+
484
+ ## Online Support
485
+
486
+ I need your opinion, ideas, user experience - that is why you can ask me about this gem via skype: **ilya.killich**
487
+
488
+ ## About author
489
+
490
+ Yes, It's true - I was a school teacher in the past.
491
+ That's why my login is the-teacher.
492
+ Now I'm ruby & frontend developer.
493
+ I learn, I teach, I make a code. And sorry for my English.
241
494
 
242
495
  ## Contributing
243
496
 
244
497
  1. Fork it
245
- 2. Create your feature branch (`git checkout -b my-new-feature`)
246
- 3. Commit your changes (`git commit -am 'Add some feature'`)
247
- 4. Push to the branch (`git push origin my-new-feature`)
248
- 5. Create new Pull Request
498
+ 2. Clone it into local folder
499
+ 3. Add to Gemfile via **gem 'the_comments', path: '/path/to/gem/the_comments'**
500
+ 4. Change code
501
+ 5. git push origin master
502
+ 6. Create pull request via github
503
+
504
+ ### MIT License
505
+
506
+ Copyright (c) 2013 Ilya N. Zykin
507
+
508
+ Permission is hereby granted, free of charge, to any person obtaining
509
+ a copy of this software and associated documentation files (the
510
+ "Software"), to deal in the Software without restriction, including
511
+ without limitation the rights to use, copy, modify, merge, publish,
512
+ distribute, sublicense, and/or sell copies of the Software, and to
513
+ permit persons to whom the Software is furnished to do so, subject to
514
+ the following conditions:
515
+
516
+ The above copyright notice and this permission notice shall be
517
+ included in all copies or substantial portions of the Software.
518
+
519
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
520
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
521
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
522
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
523
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
524
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
525
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.