the_comments 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc.example +1 -0
- data/.travis.yml +5 -0
- data/README.md +105 -425
- data/app/assets/javascripts/the_comments.js.coffee +12 -9
- data/app/assets/javascripts/the_comments_manage.js.coffee +19 -49
- data/app/assets/stylesheets/the_comments.css.scss +20 -29
- data/app/controllers/_templates_/comments_controller.rb +44 -0
- data/app/controllers/concerns/controller.rb +216 -0
- data/app/helpers/render_comments_tree_helper.rb +4 -7
- data/app/models/_templates_/comment.rb +38 -0
- data/app/models/concerns/comment.rb +103 -0
- data/app/models/concerns/comment_states.rb +80 -0
- data/app/models/concerns/commentable.rb +69 -0
- data/app/models/concerns/user.rb +52 -0
- data/app/views/the_comments/_tree.html.erb +3 -0
- data/app/views/the_comments/haml/_additional_info.html.haml +13 -0
- data/app/views/the_comments/{_comment.html.haml → haml/_comment.html.haml} +0 -0
- data/app/views/the_comments/haml/_comment_body.html.haml +20 -0
- data/app/views/the_comments/haml/_comment_edit.html.haml +26 -0
- data/app/views/the_comments/{_form.html.haml → haml/_form.html.haml} +8 -6
- data/app/views/the_comments/haml/_manage_controls.html.haml +27 -0
- data/app/views/the_comments/haml/_sidebar.html.haml +28 -0
- data/app/views/the_comments/haml/_tree.html.haml +4 -0
- data/app/views/the_comments/haml/index.html.haml +18 -0
- data/app/views/the_comments/haml/manage.html.haml +25 -0
- data/app/views/the_comments/haml/my_comments.html.haml +28 -0
- data/app/views/the_comments/slim/_additional_info.html.slim +13 -0
- data/app/views/the_comments/slim/_comment.html.slim +1 -0
- data/app/views/the_comments/slim/_comment_body.html.slim +20 -0
- data/app/views/the_comments/slim/_comment_edit.html.slim +26 -0
- data/app/views/the_comments/slim/_form.html.slim +27 -0
- data/app/views/the_comments/slim/_manage_controls.html.slim +27 -0
- data/app/views/the_comments/slim/_sidebar.html.slim +28 -0
- data/app/views/the_comments/slim/_tree.html.slim +4 -0
- data/app/views/the_comments/slim/index.html.slim +18 -0
- data/app/views/the_comments/slim/manage.html.slim +25 -0
- data/app/views/the_comments/slim/my_comments.html.slim +28 -0
- data/{lib/generators/the_comments/templates → config/initializers}/the_comments.rb +3 -0
- data/config/locales/en.yml +39 -14
- data/config/locales/ru.yml +67 -0
- data/config/routes.rb +17 -13
- data/db/migrate/20130101010101_change_user.rb +18 -0
- data/db/migrate/20130101010102_create_comments.rb +50 -0
- data/db/migrate/20130101010103_change_commentable.rb +13 -0
- data/docs/admin_ui_installation.md +145 -0
- data/docs/advanced_installation.md +182 -0
- data/docs/comment_api.md +58 -0
- data/docs/commentable_api.md +59 -0
- data/docs/config_file.md +27 -0
- data/docs/content_preprocessors.md +73 -0
- data/docs/customazation_of_views.md +30 -0
- data/docs/denormalization_and_recent_comments.md +40 -0
- data/docs/documentation.md +28 -0
- data/docs/mountable_routes.md +80 -0
- data/docs/pagination.md +123 -0
- data/docs/screencast.jpg +0 -0
- data/docs/user_api.md +75 -0
- data/docs/what_is_comcoms.md +63 -0
- data/docs/whats_wrong_with_other_gems.md +18 -0
- data/docs/where_is_example_application.md +37 -0
- data/gem_version.rb +3 -0
- data/lib/generators/the_comments/USAGE +31 -20
- data/lib/generators/the_comments/the_comments_generator.rb +35 -18
- data/lib/generators/the_comments/views_generator.rb +52 -16
- data/lib/the_comments/config.rb +14 -1
- data/lib/the_comments/version.rb +1 -3
- data/lib/the_comments.rb +10 -0
- data/spec/dummy_app/.gitignore +17 -0
- data/spec/dummy_app/.rspec +1 -0
- data/spec/dummy_app/.ruby-gemset +1 -0
- data/spec/dummy_app/.ruby-version +1 -0
- data/spec/dummy_app/Gemfile +43 -0
- data/spec/dummy_app/README.md +50 -0
- data/spec/dummy_app/Rakefile +6 -0
- data/spec/dummy_app/app/assets/images/.keep +0 -0
- data/spec/dummy_app/app/assets/javascripts/admin_panel.js +5 -0
- data/spec/dummy_app/app/assets/javascripts/application.js +16 -0
- data/spec/dummy_app/app/assets/stylesheets/admin_panel.css +3 -0
- data/spec/dummy_app/app/assets/stylesheets/app.css.scss +4 -0
- data/spec/dummy_app/app/assets/stylesheets/application.css +16 -0
- data/spec/dummy_app/app/controllers/application_controller.rb +7 -0
- data/{lib/generators/the_comments/templates → spec/dummy_app/app/controllers}/comments_controller.rb +3 -1
- data/spec/dummy_app/app/controllers/concerns/.keep +0 -0
- data/spec/dummy_app/app/controllers/posts_controller.rb +13 -0
- data/spec/dummy_app/app/controllers/users_controller.rb +7 -0
- data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
- data/spec/dummy_app/app/mailers/.keep +0 -0
- data/spec/dummy_app/app/models/.keep +0 -0
- data/spec/dummy_app/app/models/comment.rb +32 -0
- data/spec/dummy_app/app/models/concerns/.keep +0 -0
- data/spec/dummy_app/app/models/post.rb +17 -0
- data/spec/dummy_app/app/models/user.rb +21 -0
- data/spec/dummy_app/app/views/layouts/admin.html.haml +25 -0
- data/spec/dummy_app/app/views/layouts/application.html.haml +20 -0
- data/spec/dummy_app/app/views/posts/index.html.haml +22 -0
- data/spec/dummy_app/app/views/posts/show.html.haml +7 -0
- data/spec/dummy_app/bin/bundle +3 -0
- data/spec/dummy_app/bin/rails +4 -0
- data/spec/dummy_app/bin/rake +4 -0
- data/spec/dummy_app/config/application.rb +23 -0
- data/spec/dummy_app/config/boot.rb +4 -0
- data/spec/dummy_app/config/database.yml +11 -0
- data/spec/dummy_app/config/environment.rb +5 -0
- data/spec/dummy_app/config/environments/development.rb +29 -0
- data/spec/dummy_app/config/environments/production.rb +80 -0
- data/spec/dummy_app/config/environments/test.rb +36 -0
- data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy_app/config/initializers/inflections.rb +16 -0
- data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
- data/spec/dummy_app/config/initializers/secret_token.rb +12 -0
- data/spec/dummy_app/config/initializers/session_store.rb +3 -0
- data/spec/dummy_app/config/initializers/sorcery.rb +437 -0
- data/spec/dummy_app/config/initializers/the_comments.rb +13 -0
- data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy_app/config/locales/en.yml +23 -0
- data/spec/dummy_app/config/routes.rb +15 -0
- data/spec/dummy_app/config.ru +4 -0
- data/spec/dummy_app/db/migrate/20130712061503_sorcery_core.rb +16 -0
- data/spec/dummy_app/db/migrate/20130712065951_create_posts.rb +11 -0
- data/spec/dummy_app/db/migrate/20131027185332_change_user.the_comments_engine.rb +19 -0
- data/spec/dummy_app/db/migrate/20131027185333_create_comments.the_comments_engine.rb +51 -0
- data/spec/dummy_app/db/migrate/20131027185334_change_commentable.the_comments_engine.rb +14 -0
- data/spec/dummy_app/db/schema.rb +74 -0
- data/spec/dummy_app/db/seeds.rb +42 -0
- data/spec/dummy_app/lib/assets/.keep +0 -0
- data/spec/dummy_app/lib/tasks/.keep +0 -0
- data/spec/dummy_app/lib/tasks/app_bootstrap.rake +15 -0
- data/spec/dummy_app/log/.keep +0 -0
- data/spec/dummy_app/public/404.html +58 -0
- data/spec/dummy_app/public/422.html +58 -0
- data/spec/dummy_app/public/500.html +57 -0
- data/spec/dummy_app/public/favicon.ico +0 -0
- data/spec/dummy_app/public/robots.txt +5 -0
- data/spec/dummy_app/spec/factories/post.rb +6 -0
- data/spec/dummy_app/spec/factories/user.rb +6 -0
- data/spec/dummy_app/spec/models/user_counters_spec.rb +339 -0
- data/spec/dummy_app/spec/spec_helper.rb +29 -0
- data/spec/dummy_app/test/controllers/.keep +0 -0
- data/spec/dummy_app/test/fixtures/.keep +0 -0
- data/spec/dummy_app/test/helpers/.keep +0 -0
- data/spec/dummy_app/test/integration/.keep +0 -0
- data/spec/dummy_app/test/mailers/.keep +0 -0
- data/spec/dummy_app/test/models/.keep +0 -0
- data/spec/dummy_app/test/test_helper.rb +15 -0
- data/spec/dummy_app/vendor/assets/javascripts/.keep +0 -0
- data/spec/dummy_app/vendor/assets/stylesheets/.keep +0 -0
- data/views_converter.rb +16 -0
- metadata +223 -45
- data/app/controllers/concerns/the_comments_controller.rb +0 -229
- data/app/controllers/concerns/the_comments_ip_controller.rb +0 -17
- data/app/controllers/concerns/the_comments_user_agent_controller.rb +0 -15
- data/app/models/concerns/the_comments_base.rb +0 -69
- data/app/models/concerns/the_comments_black_ip.rb +0 -9
- data/app/models/concerns/the_comments_black_user_agent.rb +0 -9
- data/app/models/concerns/the_comments_commentable.rb +0 -66
- data/app/models/concerns/the_comments_states.rb +0 -65
- data/app/models/concerns/the_comments_user.rb +0 -32
- data/app/views/ip_black_lists/index.html.haml +0 -17
- data/app/views/the_comments/_comment_body.html.haml +0 -30
- data/app/views/the_comments/_manage_controls.html.haml +0 -4
- data/app/views/the_comments/_tree.html.haml +0 -4
- data/app/views/the_comments/index.html.haml +0 -19
- data/app/views/the_comments/manage.html.haml +0 -29
- data/app/views/user_agent_black_lists/index.html.haml +0 -17
- data/db/migrate/20130101010101_create_comments.rb +0 -90
- data/lib/generators/the_comments/templates/ip_black_list.rb +0 -3
- data/lib/generators/the_comments/templates/ip_black_lists_controller.rb +0 -10
- data/lib/generators/the_comments/templates/the_comments_black_ip.rb +0 -9
- data/lib/generators/the_comments/templates/the_comments_black_user_agent.rb +0 -9
- data/lib/generators/the_comments/templates/user_agent_black_list.rb +0 -3
- data/lib/generators/the_comments/templates/user_agent_black_lists_controller.rb +0 -10
@@ -0,0 +1,59 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### Commentable API
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
class Post < ActiveRecord::Base
|
7
|
+
include TheCommentsCommentable
|
8
|
+
|
9
|
+
belongs_to :user
|
10
|
+
|
11
|
+
def commentable_title
|
12
|
+
try(:title) || "Undefined title"
|
13
|
+
end
|
14
|
+
|
15
|
+
def commentable_url
|
16
|
+
['', self.class.to_s.tableize, id].join('/')
|
17
|
+
end
|
18
|
+
|
19
|
+
def commentable_state
|
20
|
+
try(:state) || "published"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
@post = Post.last
|
27
|
+
|
28
|
+
# Post owner
|
29
|
+
@post.user # => User
|
30
|
+
|
31
|
+
# All comments for commentable object
|
32
|
+
@post.comments # => ActiveRecord:Collection
|
33
|
+
|
34
|
+
# Cache counters
|
35
|
+
@post.draft_comments_count # => 1
|
36
|
+
@post.published_comments_count # => 2
|
37
|
+
@post.deleted_comments_count # => 0
|
38
|
+
|
39
|
+
# equal values with direct request to database
|
40
|
+
@post.comments.with_state([:draft]).count # => 1
|
41
|
+
@post.comments.with_state([:published]).count # => 2
|
42
|
+
@post.comments.with_state([:deleted]).count # => 0
|
43
|
+
|
44
|
+
# Alias for:
|
45
|
+
# draft_comments_count + published_comments_count
|
46
|
+
@post.comments_sum # => 3
|
47
|
+
|
48
|
+
# Spam comments
|
49
|
+
@post.comments.where(spam: true) # => ActiveRecord::Relation
|
50
|
+
|
51
|
+
# recalculate cache counters
|
52
|
+
@post.recalculate_comments_counters!
|
53
|
+
|
54
|
+
# Default Denormalization methods
|
55
|
+
# should be redefined by developer
|
56
|
+
@post.commentable_title => "Maiores eos rerum numquam aut."
|
57
|
+
@post.commentable_url => "/posts/9"
|
58
|
+
@post.commentable_state => "published"
|
59
|
+
```
|
data/docs/config_file.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### TheComments config
|
4
|
+
|
5
|
+
Following rails generator will copy default config file into your application
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
bundle exec rails g the_comments config
|
9
|
+
```
|
10
|
+
|
11
|
+
**config/initializers/the_comments.rb**
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# TheComments.config.param_name => value
|
15
|
+
|
16
|
+
TheComments.configure do |config|
|
17
|
+
config.max_reply_depth = 3 # comments tree depth
|
18
|
+
config.tolerance_time = 5 # sec - after this delay user can post a comment
|
19
|
+
config.default_state = :draft # default state for comment
|
20
|
+
config.default_owner_state = :published # default state for comment for Moderator
|
21
|
+
config.empty_inputs = [:commentBody] # array of spam trap fields
|
22
|
+
config.default_title = 'Undefined title' # default commentable_title for denormalization
|
23
|
+
|
24
|
+
config.empty_trap_protection = true
|
25
|
+
config.tolerance_time_protection = true
|
26
|
+
end
|
27
|
+
```
|
@@ -0,0 +1,73 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### Text preprocessors
|
4
|
+
|
5
|
+
TheComments designed for using with text preprocessors: Textile, Markdown, Sanitize, Coderay etc.
|
6
|
+
|
7
|
+
That is why Comment model has 2 fields for user input: **raw_content** and **content**
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class CreateComments < ActiveRecord::Migration
|
11
|
+
def change
|
12
|
+
create_table :comments do |t|
|
13
|
+
# ...
|
14
|
+
|
15
|
+
t.text :raw_content
|
16
|
+
t.text :content
|
17
|
+
|
18
|
+
# ...
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
**raw_content** - field with original user's input
|
25
|
+
|
26
|
+
**content** - field with processed user's input
|
27
|
+
|
28
|
+
<hr>
|
29
|
+
|
30
|
+
**before_save :prepare_content** - provides processing of raw user's input
|
31
|
+
|
32
|
+
By default **prepare_content** looks like this:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
def prepare_content
|
36
|
+
self.content = self.raw_content
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
I think every developer should redefine this behaviour. To do this you should to use following instructions.
|
41
|
+
|
42
|
+
### Comment Model customization
|
43
|
+
|
44
|
+
invoke TheComments generator
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
bundle exec rails g the_comments models
|
48
|
+
```
|
49
|
+
|
50
|
+
This will create **app/models/comment.rb**
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Comment < ActiveRecord::Base
|
54
|
+
include TheCommentsBase
|
55
|
+
|
56
|
+
# ---------------------------------------------------
|
57
|
+
# Define your filters for content
|
58
|
+
# Expample for: gem 'RedCloth', gem 'sanitize'
|
59
|
+
# your personal SmilesProcessor
|
60
|
+
|
61
|
+
# def prepare_content
|
62
|
+
# text = self.raw_content
|
63
|
+
# text = RedCloth.new(text).to_html
|
64
|
+
# text = SmilesProcessor.new(text)
|
65
|
+
# text = Sanitize.clean(text, Sanitize::Config::RELAXED)
|
66
|
+
# self.content = text
|
67
|
+
# end
|
68
|
+
# ---------------------------------------------------
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
Just redefine **prepare_content** for your purposes
|
73
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
## Customization
|
4
|
+
|
5
|
+
You can use **rails generators** for copy files into your Application. After that you can customize almost everything
|
6
|
+
|
7
|
+
Generators list:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
bundle exec rails g the_comments --help
|
11
|
+
```
|
12
|
+
|
13
|
+
### Customization of views
|
14
|
+
|
15
|
+
Copy View files for customization:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
bundle exec rails g the_comments:views assets
|
19
|
+
bundle exec rails g the_comments:views views
|
20
|
+
```
|
21
|
+
|
22
|
+
### Customization of comments tree
|
23
|
+
|
24
|
+
Copy Helper file for tree customization:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
bundle exec rails g the_comments:views helper
|
28
|
+
```
|
29
|
+
|
30
|
+
For more info read [TheSortableTree doc](https://github.com/the-teacher/the_sortable_tree)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
## Denormalization
|
4
|
+
|
5
|
+
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.
|
6
|
+
|
7
|
+
I use denormalization of commentable objects to solve this problem.
|
8
|
+
|
9
|
+
My practice shows - We need 3 denormalized fields into comment for (request-free) building of recent comments list:
|
10
|
+
|
11
|
+
<img src="https://raw.github.com/the-teacher/the_comments/master/docs/the_comments_view_5.gif" alt="the_comments">
|
12
|
+
|
13
|
+
* **Comment#commentable_title** - for example: "My first post about Ruby On Rails"
|
14
|
+
* **Comment#commentable_url** - for example: "/posts/1-my-first-post-about-ruby-on-rails"
|
15
|
+
* **Comment#commentable_state** - for example: "draft"
|
16
|
+
|
17
|
+
That is why any **Commentable Model should have few methods** to provide denormalization for Comments.
|
18
|
+
|
19
|
+
## Recent comments building
|
20
|
+
|
21
|
+
Denormalization makes building of Recent comments (for polymorphic relationship) very easy!
|
22
|
+
|
23
|
+
Controller:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
@comments = Comment.with_state(:published)
|
27
|
+
.where(commentable_state: [:published])
|
28
|
+
.order('created_at DESC')
|
29
|
+
.page(params[:page])
|
30
|
+
```
|
31
|
+
|
32
|
+
View:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
- @comments.each do |comment|
|
36
|
+
%div
|
37
|
+
%p= comment.commentable_title
|
38
|
+
%p= link_to comment.commentable_title, comment.commentable_url
|
39
|
+
%p= comment.content
|
40
|
+
```
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#### INSTALLATION
|
2
|
+
* :white_check_mark: [ADVANCED INSTALLATION](advanced_installation.md)
|
3
|
+
* :white_check_mark: [ADMIN UI INSTALLATION](admin_ui_installation.md)
|
4
|
+
* :white_check_mark: [Mountable Routing](mountable_routes.md)
|
5
|
+
|
6
|
+
#### API
|
7
|
+
* :white_check_mark: [User API](user_api.md)
|
8
|
+
* :white_check_mark: [Comment API](comment_api.md)
|
9
|
+
* :white_check_mark: [Commentable API](commentable_api.md)
|
10
|
+
|
11
|
+
#### Understanding
|
12
|
+
* :white_check_mark: [What is ComComs?](what_is_comcoms.md)
|
13
|
+
* :white_check_mark: [Denormalization and Recent comments](denormalization_and_recent_comments.md)
|
14
|
+
* :white_check_mark: [What's wrong with other gems?](whats_wrong_with_other_gems.md)
|
15
|
+
* :white_check_mark: [Why TheComments is better than others gems?](whats_wrong_with_other_gems.md#why-thecomments-is-better-than-others-gems)
|
16
|
+
|
17
|
+
#### Customazation
|
18
|
+
* :white_check_mark: [Views](customazation_of_views.md)
|
19
|
+
* :white_check_mark: [Text Preprocessors - Sanitize, Markdown etc.](content_preprocessors.md)
|
20
|
+
|
21
|
+
#### Configuration
|
22
|
+
* :white_check_mark: [the_comments.rb config file](config_file.md)
|
23
|
+
|
24
|
+
#### Q&A
|
25
|
+
* :white_check_mark: [I want not to use kaminari for Admin UI](pagination.md)
|
26
|
+
* :white_check_mark: [Where is example application?](where_is_example_application.md)
|
27
|
+
* :white_check_mark: [How can I run tests?](where_is_example_application.md#run-tests)
|
28
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
## Mountable Routes
|
4
|
+
|
5
|
+
Now gem has mountable routes. It's was not my idea, but guys said - it's very helpful. So, ok!
|
6
|
+
|
7
|
+
You should mount routes to your app.
|
8
|
+
|
9
|
+
:warning: Default views based on **as: :comments** argument. If, you want to change it - you should customize default views.
|
10
|
+
|
11
|
+
**config/routes.rb**
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
MyApp::Application.routes.draw do
|
15
|
+
root 'posts#index'
|
16
|
+
resources :posts
|
17
|
+
|
18
|
+
# ...
|
19
|
+
|
20
|
+
mount TheComments::Engine => '/', as: :comments
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
And after that you can see routes:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
rake routes | grep comments
|
28
|
+
```
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
comments / TheComments::Engine
|
32
|
+
to_spam_comment POST /comments/:id/to_spam(.:format) comments#to_spam
|
33
|
+
to_draft_comment POST /comments/:id/to_draft(.:format) comments#to_draft
|
34
|
+
to_published_comment POST /comments/:id/to_published(.:format) comments#to_published
|
35
|
+
to_deleted_comment DELETE /comments/:id/to_deleted(.:format) comments#to_deleted
|
36
|
+
manage_comments GET /comments/manage(.:format) comments#manage
|
37
|
+
my_draft_comments GET /comments/my_draft(.:format) comments#my_draft
|
38
|
+
my_published_comments GET /comments/my_published(.:format) comments#my_published
|
39
|
+
my_comments_comments GET /comments/my_comments(.:format) comments#my_comments
|
40
|
+
total_draft_comments GET /comments/total_draft(.:format) comments#total_draft
|
41
|
+
total_published_comments GET /comments/total_published(.:format) comments#total_published
|
42
|
+
total_deleted_comments GET /comments/total_deleted(.:format) comments#total_deleted
|
43
|
+
total_spam_comments GET /comments/total_spam(.:format) comments#total_spam
|
44
|
+
draft_comments GET /comments/draft(.:format) comments#draft
|
45
|
+
published_comments GET /comments/published(.:format) comments#published
|
46
|
+
deleted_comments GET /comments/deleted(.:format) comments#deleted
|
47
|
+
spam_comments GET /comments/spam(.:format) comments#spam
|
48
|
+
comments GET /comments(.:format) comments#index
|
49
|
+
POST /comments(.:format) comments#create
|
50
|
+
new_comment GET /comments/new(.:format) comments#new
|
51
|
+
edit_comment GET /comments/:id/edit(.:format) comments#edit
|
52
|
+
comment GET /comments/:id(.:format) comments#show
|
53
|
+
PATCH /comments/:id(.:format) comments#update
|
54
|
+
PUT /comments/:id(.:format) comments#update
|
55
|
+
DELETE /comments/:id(.:format) comments#destroy
|
56
|
+
```
|
57
|
+
|
58
|
+
And now you can use url helpers with 2 ways:
|
59
|
+
|
60
|
+
### Way 1. Url Helpers
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
= link_to 'link', comments.comments_path
|
64
|
+
= link_to 'link', comments.manage_comments_path
|
65
|
+
= link_to 'link', comments.new_comment_path
|
66
|
+
|
67
|
+
= link_to 'link', comments.comment_path(@comment)
|
68
|
+
= link_to 'link', comments.to_spam_comment_path(@comment)
|
69
|
+
```
|
70
|
+
|
71
|
+
### Way 2. Array notation
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
= link_to 'link', [comments, :index]
|
75
|
+
= link_to 'link', [comments, :manage]
|
76
|
+
= link_to 'link', [comments, :new]
|
77
|
+
|
78
|
+
= link_to 'link', [comments, @comment]
|
79
|
+
= link_to 'link', [comments, :to_spam, @comment]
|
80
|
+
```
|
data/docs/pagination.md
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
## I want not to use kaminari for Admin UI
|
4
|
+
|
5
|
+
By default we use Kaminari pagination for Admin UI.
|
6
|
+
|
7
|
+
But you can change this. For example, your **comments_controller.rb** looks like this:
|
8
|
+
|
9
|
+
**app/controllers/comments_controller.rb**
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class CommentsController < ApplicationController
|
13
|
+
# layout 'admin'
|
14
|
+
|
15
|
+
# Define your restrict methods and use them like this:
|
16
|
+
#
|
17
|
+
# before_action :user_required, except: %w[index create]
|
18
|
+
# before_action :owner_required, except: %w[index create]
|
19
|
+
# before_action :admin_required, only: %w[total_draft total_published total_deleted total_spam]
|
20
|
+
|
21
|
+
include TheComments::Controller
|
22
|
+
|
23
|
+
# >>> include TheComments::Controller <<<
|
24
|
+
# (!) Almost all methods based on *current_user* method
|
25
|
+
#
|
26
|
+
# 1. Controller's public methods list:
|
27
|
+
# You can redifine it for your purposes
|
28
|
+
# public
|
29
|
+
# %w[ manage index create edit update ]
|
30
|
+
# %w[ my_comments my_draft my_published ]
|
31
|
+
# %w[ draft published deleted spam ]
|
32
|
+
# %w[ to_draft to_published to_deleted to_spam ]
|
33
|
+
# %w[ total_draft total_published total_deleted total_spam ]
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# 2. Controller's private methods list:
|
37
|
+
# You can redifine it for your purposes
|
38
|
+
#
|
39
|
+
# private
|
40
|
+
# %w[ comment_template comment_partial ]
|
41
|
+
# %w[ denormalized_fields request_data_for_comment define_commentable ]
|
42
|
+
# %w[ comment_params patch_comment_params ]
|
43
|
+
# %w[ ajax_requests_required cookies_required ]
|
44
|
+
# %w[ empty_trap_required tolerance_time_required ]
|
45
|
+
|
46
|
+
# KAMINARI pagination:
|
47
|
+
# following methods based on gem "kaminari"
|
48
|
+
# You should redefine them if you use something else
|
49
|
+
#
|
50
|
+
# public
|
51
|
+
# %w[ manage index edit ]
|
52
|
+
# %w[ draft published deleted spam ]
|
53
|
+
# %w[ my_comments my_draft my_published ]
|
54
|
+
# %w[ total_draft total_published total_deleted total_spam ]
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
There is we can see comments about kaminari. So, we can try to change it.
|
59
|
+
|
60
|
+
There is example how it can be in your real app:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class CommentsController < ApplicationController
|
64
|
+
layout 'admin'
|
65
|
+
|
66
|
+
before_action :user_required, except: %w[index create]
|
67
|
+
before_action :owner_required, except: %w[index create]
|
68
|
+
before_action :admin_required, only: %w[total_draft total_published total_deleted total_spam]
|
69
|
+
|
70
|
+
include TheComments::Controller
|
71
|
+
|
72
|
+
public
|
73
|
+
|
74
|
+
def index
|
75
|
+
@comments = ::Comment.with_state(:published).recent.super_paginator(params)
|
76
|
+
render comment_template(:index)
|
77
|
+
end
|
78
|
+
|
79
|
+
def manage
|
80
|
+
@comments = current_user.comcoms.active.recent.super_paginator(params)
|
81
|
+
render comment_template(:manage)
|
82
|
+
end
|
83
|
+
|
84
|
+
def my_comments
|
85
|
+
@comments = current_user.my_comments.active.recent.super_paginator(params)
|
86
|
+
render comment_template(:my_comments)
|
87
|
+
end
|
88
|
+
|
89
|
+
def edit
|
90
|
+
@comments = current_user.comcoms.where(id: params[:id]).super_paginator(params)
|
91
|
+
render comment_template(:manage)
|
92
|
+
end
|
93
|
+
|
94
|
+
%w[draft published deleted].each do |state|
|
95
|
+
define_method "#{state}" do
|
96
|
+
@comments = current_user.comcoms.with_state(state).recent.super_paginator(params)
|
97
|
+
render comment_template(:manage)
|
98
|
+
end
|
99
|
+
|
100
|
+
define_method "total_#{state}" do
|
101
|
+
@comments = ::Comment.with_state(state).recent.super_paginator(params)
|
102
|
+
render comment_template(:manage)
|
103
|
+
end
|
104
|
+
|
105
|
+
unless state == 'deleted'
|
106
|
+
define_method "my_#{state}" do
|
107
|
+
@comments = current_user.my_comments.with_state(state).recent.super_paginator(params)
|
108
|
+
render comment_template(:my_comments)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def spam
|
114
|
+
@comments = current_user.comcoms.where(spam: true).recent.super_paginator(params)
|
115
|
+
render comment_template(:manage)
|
116
|
+
end
|
117
|
+
|
118
|
+
def total_spam
|
119
|
+
@comments = ::Comment.where(spam: true).recent.super_paginator(params)
|
120
|
+
render comment_template(:manage)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
data/docs/screencast.jpg
ADDED
Binary file
|
data/docs/user_api.md
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### User API
|
4
|
+
|
5
|
+
**When User is not commentable model**
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class User < ActiveRecord::Base
|
9
|
+
include TheCommentsUser
|
10
|
+
|
11
|
+
has_many :posts # commentable model
|
12
|
+
has_many :products # commentable model
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
:warning: Please, read this: [What is ComComs?](what_is_comcoms.md)
|
17
|
+
|
18
|
+
|
19
|
+
We can use following methods
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
@user = User.first
|
23
|
+
|
24
|
+
@user.comcoms #=> all comments for posts and products, where user is owner
|
25
|
+
|
26
|
+
# cache counters
|
27
|
+
@user.draft_comcoms_count # => 1
|
28
|
+
@user.published_comcoms_count # => 5
|
29
|
+
@user.deleted_comcoms_count # => 3
|
30
|
+
@user.spam_comcoms_count # => 2
|
31
|
+
|
32
|
+
# equal values, but with request to database
|
33
|
+
@user.comcoms.with_state([:draft]).count # => 1
|
34
|
+
@user.comcoms.with_state([:published]).count # => 5
|
35
|
+
@user.comcoms.with_state([:deleted]).count # => 3
|
36
|
+
@user.comcoms.where(spam: true).count # => 2
|
37
|
+
|
38
|
+
# draft and published comments
|
39
|
+
# written by this user
|
40
|
+
@user.my_comments # => ActiveRecord::Relation
|
41
|
+
|
42
|
+
# cache counters for comments
|
43
|
+
# written by this user
|
44
|
+
# there is no cache counter for deleted state!
|
45
|
+
@user.my_draft_comments_count # => 3
|
46
|
+
@user.my_published_comments_count # => 7
|
47
|
+
|
48
|
+
# equal values, but with request to database
|
49
|
+
@user.my_draft_comments.count # => 3
|
50
|
+
@user.my_published_comments.count # => 7
|
51
|
+
@user.my_deleted_comments.count # => 1
|
52
|
+
|
53
|
+
# helper methods to get comments
|
54
|
+
# written by this user
|
55
|
+
@user.my_draft_comments # => ActiveRecord::Relation
|
56
|
+
@user.my_published_comments # => ActiveRecord::Relation
|
57
|
+
@user.my_deleted_comments # => ActiveRecord::Relation
|
58
|
+
|
59
|
+
# recalculate cache counters
|
60
|
+
@user.recalculate_my_comments_counter!
|
61
|
+
```
|
62
|
+
|
63
|
+
**When User is commentable model**
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
class User < ActiveRecord::Base
|
67
|
+
include TheCommentsUser
|
68
|
+
include TheCommentsCommentable
|
69
|
+
|
70
|
+
has_many :posts # commentable model
|
71
|
+
has_many :products # commentable model
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
you should to use following instruction [Commentable API](commentable_api.md)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### What is ComComs?
|
4
|
+
|
5
|
+
:warning: **comcoms** - is main method to get all comments related with user's commentable models.
|
6
|
+
|
7
|
+
:warning: **comments** - is main method to get comments related with any commentable model.
|
8
|
+
|
9
|
+
**ComComs** - **com**ments of **com**mentable models
|
10
|
+
|
11
|
+
ComComs are all incoming comments for all models, where this user is owner.
|
12
|
+
|
13
|
+
For example, some user **has_many :posts**, and **has_many :products** - all comments for all user's posts and all user's products called as **comcoms**.
|
14
|
+
|
15
|
+
#### Why we need ComComs?
|
16
|
+
|
17
|
+
User model can be commentable too. For example to build user's "public wall" (like tweets list for current user).
|
18
|
+
|
19
|
+
And we should to separate **comments** attached to user model (tweets) and comments attached to any another user's model.
|
20
|
+
|
21
|
+
That is why User model in-fact has following relationship declarations:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
has_many :comcoms, class_name: :Comment, foreign_key: :holder_id
|
26
|
+
|
27
|
+
# and if User model is commentable model
|
28
|
+
# has_many :comments, as: :commentable
|
29
|
+
|
30
|
+
has_many :posts
|
31
|
+
has_many :products
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
in real application it should be described like this:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
class User < ActiveRecord::Base
|
39
|
+
include TheCommentsUser
|
40
|
+
include TheCommentsCommentable
|
41
|
+
|
42
|
+
has_many :posts
|
43
|
+
has_many :products
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
But in most popular situation User model should not be commentable, and you should use only **comcoms** method to get all comments related with this user:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class User < ActiveRecord::Base
|
51
|
+
include TheCommentsUser
|
52
|
+
|
53
|
+
has_many :posts
|
54
|
+
has_many :products
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
and later in your application
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
@user = User.find params[:id]
|
62
|
+
@user.comcoms.count # => 42
|
63
|
+
```
|
@@ -0,0 +1,18 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### What's wrong with other gems?
|
4
|
+
|
5
|
+
Just look at [Ruby-Toolbox](https://www.ruby-toolbox.com/categories/rails_comments). What we can see?
|
6
|
+
|
7
|
+
* [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.
|
8
|
+
* [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.
|
9
|
+
* [opinio](https://github.com/Draiken/opinio) - looks better, but there is no threading. I want to have more!
|
10
|
+
* [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.
|
11
|
+
|
12
|
+
### Why TheComments is better than others gems?
|
13
|
+
|
14
|
+
1. Only TheComments has special helper for tree rendering ([TheSortableTree](https://github.com/the-teacher/the_sortable_tree)).
|
15
|
+
2. TheComments designed to reduce requests to database. I say about useful cache counters.
|
16
|
+
3. TheComments has solution for [building of Recent Comments](https://github.com/the-teacher/the_comments/blob/master/docs/denormalization_and_recent_comments.md) (for polymorphic relations)
|
17
|
+
4. TheComments designed for text preprocessors (Textile, Markdown, Sanitize, Coderay etc.)
|
18
|
+
5. TheComments has admin UI based on bootstrap 3
|
@@ -0,0 +1,37 @@
|
|
1
|
+
← [documentation](documentation.md)
|
2
|
+
|
3
|
+
### Dummy Application
|
4
|
+
|
5
|
+
Repo of TheComments has dummy application for developmet and testing.
|
6
|
+
|
7
|
+
It's here: [Dummy App](https://github.com/the-teacher/the_comments/tree/master/spec/dummy_app)
|
8
|
+
|
9
|
+
For run dummy app, your should do that:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
git clone https://github.com/the-teacher/the_comments.git
|
13
|
+
|
14
|
+
cd the_comments/spec/dummy_app/
|
15
|
+
|
16
|
+
bundle
|
17
|
+
|
18
|
+
rake db:bootstrap_and_seed
|
19
|
+
|
20
|
+
rails s -p 3000 -b localhost
|
21
|
+
```
|
22
|
+
|
23
|
+
### Run tests
|
24
|
+
|
25
|
+
Following instructions should helps to run simple tests:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
git clone https://github.com/the-teacher/the_comments.git
|
29
|
+
|
30
|
+
cd the_comments/spec/dummy_app/
|
31
|
+
|
32
|
+
bundle
|
33
|
+
|
34
|
+
rake db:bootstrap RAILS_ENV=test
|
35
|
+
|
36
|
+
rspec --format documentation
|
37
|
+
```
|
data/gem_version.rb
ADDED