the_comments 1.1.0 → 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/.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