fuck_comments 2.3.4

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.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +30 -0
  3. data/.ruby-gemset.example +1 -0
  4. data/.ruby-version.example +1 -0
  5. data/.rvmrc.example +1 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +338 -0
  10. data/Rakefile +1 -0
  11. data/app/assets/javascripts/the_comments.js.coffee +108 -0
  12. data/app/assets/javascripts/the_comments_manage.js.coffee +27 -0
  13. data/app/assets/stylesheets/the_comments.css.scss +248 -0
  14. data/app/controllers/_templates_/comments_controller.rb +44 -0
  15. data/app/controllers/concerns/the_comments/controller.rb +197 -0
  16. data/app/controllers/concerns/the_comments/view_token.rb +20 -0
  17. data/app/helpers/render_comments_tree_helper.rb +111 -0
  18. data/app/models/_templates_/comment.rb +38 -0
  19. data/app/models/concerns/the_comments/comment.rb +116 -0
  20. data/app/models/concerns/the_comments/comment_states.rb +80 -0
  21. data/app/models/concerns/the_comments/commentable.rb +69 -0
  22. data/app/models/concerns/the_comments/user.rb +56 -0
  23. data/app/views/the_comments/_tree.html.erb +3 -0
  24. data/app/views/the_comments/haml/_additional_info.html.haml +13 -0
  25. data/app/views/the_comments/haml/_comment.html.haml +1 -0
  26. data/app/views/the_comments/haml/_comment_body.html.haml +25 -0
  27. data/app/views/the_comments/haml/_comment_edit.html.haml +26 -0
  28. data/app/views/the_comments/haml/_form.html.haml +8 -0
  29. data/app/views/the_comments/haml/_guest_form.html.haml +22 -0
  30. data/app/views/the_comments/haml/_logined_form.html.haml +18 -0
  31. data/app/views/the_comments/haml/_manage_controls.html.haml +30 -0
  32. data/app/views/the_comments/haml/_sidebar.html.haml +9 -0
  33. data/app/views/the_comments/haml/_sidebar_admin.html.haml +12 -0
  34. data/app/views/the_comments/haml/_sidebar_backlink.html.haml +3 -0
  35. data/app/views/the_comments/haml/_sidebar_user.html.haml +29 -0
  36. data/app/views/the_comments/haml/_tree.html.haml +16 -0
  37. data/app/views/the_comments/haml/manage.html.haml +26 -0
  38. data/app/views/the_comments/slim/_additional_info.html.slim +13 -0
  39. data/app/views/the_comments/slim/_comment.html.slim +1 -0
  40. data/app/views/the_comments/slim/_comment_body.html.slim +24 -0
  41. data/app/views/the_comments/slim/_comment_edit.html.slim +26 -0
  42. data/app/views/the_comments/slim/_form.html.slim +8 -0
  43. data/app/views/the_comments/slim/_guest_form.html.slim +22 -0
  44. data/app/views/the_comments/slim/_logined_form.html.slim +18 -0
  45. data/app/views/the_comments/slim/_manage_controls.html.slim +30 -0
  46. data/app/views/the_comments/slim/_sidebar.html.slim +9 -0
  47. data/app/views/the_comments/slim/_sidebar_admin.html.slim +12 -0
  48. data/app/views/the_comments/slim/_sidebar_backlink.html.slim +3 -0
  49. data/app/views/the_comments/slim/_sidebar_user.html.slim +29 -0
  50. data/app/views/the_comments/slim/_tree.html.slim +16 -0
  51. data/app/views/the_comments/slim/index.html.slim +18 -0
  52. data/app/views/the_comments/slim/manage.html.slim +26 -0
  53. data/app/views/the_comments/slim/my_comments.html.slim +28 -0
  54. data/config/initializers/the_comments.rb +15 -0
  55. data/config/locales/en.yml +68 -0
  56. data/config/locales/ru.yml +71 -0
  57. data/config/routes.rb +38 -0
  58. data/db/migrate/20130101010101_the_comments_change_user.rb +18 -0
  59. data/db/migrate/20130101010102_the_comments_create_comments.rb +50 -0
  60. data/db/migrate/20130101010103_the_comments_change_commentable.rb +13 -0
  61. data/docs/admin_ui_installation.md +145 -0
  62. data/docs/advanced_installation.md +185 -0
  63. data/docs/comment_api.md +58 -0
  64. data/docs/commentable_api.md +59 -0
  65. data/docs/config_file.md +27 -0
  66. data/docs/content_preprocessors.md +73 -0
  67. data/docs/customazation_of_views.md +30 -0
  68. data/docs/denormalization_and_recent_comments.md +40 -0
  69. data/docs/documentation.md +29 -0
  70. data/docs/generators.md +74 -0
  71. data/docs/pagination.md +123 -0
  72. data/docs/routes.md +77 -0
  73. data/docs/screencast.jpg +0 -0
  74. data/docs/the_comments.jpg +0 -0
  75. data/docs/the_comments_view_1.gif +0 -0
  76. data/docs/the_comments_view_2.gif +0 -0
  77. data/docs/the_comments_view_3.gif +0 -0
  78. data/docs/the_comments_view_4.gif +0 -0
  79. data/docs/the_comments_view_5.gif +0 -0
  80. data/docs/user_api.md +75 -0
  81. data/docs/what_is_comcoms.md +63 -0
  82. data/docs/whats_wrong_with_other_gems.md +28 -0
  83. data/docs/where_is_example_application.md +37 -0
  84. data/gem_version.rb +3 -0
  85. data/lib/generators/the_comments/USAGE +44 -0
  86. data/lib/generators/the_comments/the_comments_generator.rb +56 -0
  87. data/lib/generators/the_comments/views_generator.rb +79 -0
  88. data/lib/the_comments/config.rb +39 -0
  89. data/lib/the_comments/version.rb +1 -0
  90. data/lib/the_comments.rb +27 -0
  91. data/spec/dummy_app/.gitignore +18 -0
  92. data/spec/dummy_app/.rspec +1 -0
  93. data/spec/dummy_app/Gemfile +43 -0
  94. data/spec/dummy_app/README.md +33 -0
  95. data/spec/dummy_app/Rakefile +6 -0
  96. data/spec/dummy_app/app/assets/images/.keep +0 -0
  97. data/spec/dummy_app/app/assets/javascripts/admin_panel.js +5 -0
  98. data/spec/dummy_app/app/assets/javascripts/application.js +16 -0
  99. data/spec/dummy_app/app/assets/stylesheets/admin_panel.css +3 -0
  100. data/spec/dummy_app/app/assets/stylesheets/app.css.scss +4 -0
  101. data/spec/dummy_app/app/assets/stylesheets/application.css +16 -0
  102. data/spec/dummy_app/app/controllers/application_controller.rb +7 -0
  103. data/spec/dummy_app/app/controllers/comments_controller.rb +28 -0
  104. data/spec/dummy_app/app/controllers/concerns/.keep +0 -0
  105. data/spec/dummy_app/app/controllers/posts_controller.rb +13 -0
  106. data/spec/dummy_app/app/controllers/users_controller.rb +7 -0
  107. data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
  108. data/spec/dummy_app/app/mailers/.keep +0 -0
  109. data/spec/dummy_app/app/models/.keep +0 -0
  110. data/spec/dummy_app/app/models/comment.rb +32 -0
  111. data/spec/dummy_app/app/models/concerns/.keep +0 -0
  112. data/spec/dummy_app/app/models/post.rb +17 -0
  113. data/spec/dummy_app/app/models/user.rb +21 -0
  114. data/spec/dummy_app/app/views/layouts/admin.html.haml +25 -0
  115. data/spec/dummy_app/app/views/layouts/application.html.haml +20 -0
  116. data/spec/dummy_app/app/views/posts/index.html.haml +22 -0
  117. data/spec/dummy_app/app/views/posts/show.html.haml +7 -0
  118. data/spec/dummy_app/bin/bundle +3 -0
  119. data/spec/dummy_app/bin/rails +4 -0
  120. data/spec/dummy_app/bin/rake +4 -0
  121. data/spec/dummy_app/config/application.rb +23 -0
  122. data/spec/dummy_app/config/boot.rb +4 -0
  123. data/spec/dummy_app/config/database.yml +11 -0
  124. data/spec/dummy_app/config/environment.rb +5 -0
  125. data/spec/dummy_app/config/environments/development.rb +29 -0
  126. data/spec/dummy_app/config/environments/production.rb +80 -0
  127. data/spec/dummy_app/config/environments/test.rb +36 -0
  128. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  129. data/spec/dummy_app/config/initializers/filter_parameter_logging.rb +4 -0
  130. data/spec/dummy_app/config/initializers/inflections.rb +16 -0
  131. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  132. data/spec/dummy_app/config/initializers/secret_token.rb +12 -0
  133. data/spec/dummy_app/config/initializers/session_store.rb +3 -0
  134. data/spec/dummy_app/config/initializers/sorcery.rb +437 -0
  135. data/spec/dummy_app/config/initializers/the_comments.rb +15 -0
  136. data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
  137. data/spec/dummy_app/config/locales/en.yml +23 -0
  138. data/spec/dummy_app/config/routes.rb +19 -0
  139. data/spec/dummy_app/config.ru +4 -0
  140. data/spec/dummy_app/db/migrate/20130712061503_sorcery_core.rb +16 -0
  141. data/spec/dummy_app/db/migrate/20130712065951_create_posts.rb +11 -0
  142. data/spec/dummy_app/db/migrate/20131027185332_change_user.the_comments_engine.rb +19 -0
  143. data/spec/dummy_app/db/migrate/20131027185333_create_comments.the_comments_engine.rb +51 -0
  144. data/spec/dummy_app/db/migrate/20131027185334_change_commentable.the_comments_engine.rb +14 -0
  145. data/spec/dummy_app/db/schema.rb +74 -0
  146. data/spec/dummy_app/db/seeds.rb +42 -0
  147. data/spec/dummy_app/lib/assets/.keep +0 -0
  148. data/spec/dummy_app/lib/tasks/.keep +0 -0
  149. data/spec/dummy_app/lib/tasks/app_bootstrap.rake +15 -0
  150. data/spec/dummy_app/log/.keep +0 -0
  151. data/spec/dummy_app/public/404.html +58 -0
  152. data/spec/dummy_app/public/422.html +58 -0
  153. data/spec/dummy_app/public/500.html +57 -0
  154. data/spec/dummy_app/public/favicon.ico +0 -0
  155. data/spec/dummy_app/public/robots.txt +5 -0
  156. data/spec/dummy_app/spec/factories/post.rb +6 -0
  157. data/spec/dummy_app/spec/factories/user.rb +6 -0
  158. data/spec/dummy_app/spec/models/user_counters_spec.rb +339 -0
  159. data/spec/dummy_app/spec/spec_helper.rb +29 -0
  160. data/spec/dummy_app/test/controllers/.keep +0 -0
  161. data/spec/dummy_app/test/fixtures/.keep +0 -0
  162. data/spec/dummy_app/test/helpers/.keep +0 -0
  163. data/spec/dummy_app/test/integration/.keep +0 -0
  164. data/spec/dummy_app/test/mailers/.keep +0 -0
  165. data/spec/dummy_app/test/models/.keep +0 -0
  166. data/spec/dummy_app/test/test_helper.rb +15 -0
  167. data/spec/dummy_app/vendor/assets/javascripts/.keep +0 -0
  168. data/spec/dummy_app/vendor/assets/stylesheets/.keep +0 -0
  169. data/the_comments.gemspec +23 -0
  170. data/views_converter.rb +16 -0
  171. metadata +332 -0
@@ -0,0 +1,185 @@
1
+ ←   [documentation](documentation.md)
2
+
3
+ ## Advanced Installation
4
+
5
+ ### 1. Gems install
6
+
7
+ **Gemfile**
8
+
9
+ ```ruby
10
+ gem 'the_comments', "~> 2.0"
11
+
12
+ gem 'haml' # or gem 'slim'
13
+ gem 'awesome_nested_set' # or same gem
14
+ ```
15
+
16
+ **Bundle**
17
+
18
+ ```
19
+ bundle
20
+ ```
21
+
22
+ ### 2. Migrations install
23
+
24
+ **Copy migrations**
25
+
26
+ ```
27
+ rake the_comments_engine:install:migrations
28
+ ```
29
+
30
+ Will create:
31
+
32
+ * xxxxx_change_user.rb
33
+ * xxxxx_create_comments.rb
34
+ * xxxxx_change_commentable.rb
35
+
36
+ :warning:   **Open and change xxxxx_change_commentable.rb migration**
37
+
38
+ ```ruby
39
+ class ChangeCommentable < ActiveRecord::Migration
40
+ def change
41
+ # Additional fields to Commentable Models
42
+ # [:posts, :articles, ... ]
43
+
44
+ # There is only Post model is commentable
45
+ [:posts].each do |table_name|
46
+ change_table table_name do |t|
47
+ t.integer :draft_comments_count, default: 0
48
+ t.integer :published_comments_count, default: 0
49
+ t.integer :deleted_comments_count, default: 0
50
+ end
51
+ end
52
+ end
53
+ end
54
+ ```
55
+
56
+ **Invoke migrations**
57
+
58
+ ```
59
+ rake db:migrate
60
+ ```
61
+
62
+ ### 3. Code install
63
+
64
+ ```ruby
65
+ rails g the_comments install
66
+ ```
67
+
68
+ Will create:
69
+
70
+ * config/initializers/the_comments.rb
71
+ * app/controllers/comments_controller.rb
72
+ * app/models/comment.rb
73
+
74
+ :warning: &nbsp; **Open each file and follow an instructions**
75
+
76
+ ### 4. Models modifictions
77
+
78
+ **app/models/user.rb**
79
+
80
+ ```ruby
81
+ class User < ActiveRecord::Base
82
+ include TheComments::User
83
+
84
+ has_many :posts
85
+
86
+ # Your way to define privileged users
87
+ def admin?
88
+ self == User.first
89
+ end
90
+
91
+ # Required TheComments methods for users restrictions
92
+ def comments_admin?
93
+ admin?
94
+ end
95
+
96
+ def comments_moderator? comment
97
+ id == comment.holder_id
98
+ end
99
+ end
100
+ ```
101
+
102
+ **app/models/post.rb**
103
+
104
+ ```ruby
105
+ class Post < ActiveRecord::Base
106
+ include TheComments::Commentable
107
+
108
+ belongs_to :user
109
+
110
+ # Denormalization methods
111
+ # Migration: t.string :title
112
+ # => "My new awesome post"
113
+ def commentable_title
114
+ try(:title) || "Undefined post title"
115
+ end
116
+
117
+ # => your way to build URL
118
+ # => "/posts/254"
119
+ def commentable_url
120
+ ['', self.class.to_s.tableize, id].join('/')
121
+ end
122
+
123
+ # gem 'state_machine'
124
+ # Migration: t.string :state
125
+ # => "published" | "draft" | "deleted"
126
+ def commentable_state
127
+ try(:state) || "published"
128
+ end
129
+ end
130
+ ```
131
+
132
+ ### 5. Mount Engine routes
133
+
134
+ **config/routes.rb**
135
+
136
+ ```ruby
137
+ MyApp::Application.routes.draw do
138
+ root 'posts#index'
139
+ resources :posts
140
+
141
+ # ...
142
+
143
+ # TheComments routes
144
+ concern :user_comments, TheComments::UserRoutes.new
145
+ concern :admin_comments, TheComments::AdminRoutes.new
146
+ resources :comments, concerns: [:user_comments, :admin_comments]
147
+ end
148
+ ```
149
+
150
+ Please, read [documentation](docs/documentation.md) to learn more
151
+
152
+ ### 6. Assets install
153
+
154
+ **app/assets/stylesheets/application.css**
155
+
156
+ ```css
157
+ /*
158
+ *= require the_comments
159
+ */
160
+ ```
161
+
162
+ **app/assets/javascripts/application.js**
163
+
164
+ ```js
165
+ //= require the_comments
166
+ ```
167
+
168
+ ### 7. Controller code example
169
+
170
+ **app/controllers/posts_controllers.rb**
171
+
172
+ ```ruby
173
+ def show
174
+ @post = Post.find params[:id]
175
+ @comments = @post.comments.with_state([:draft, :published])
176
+ end
177
+ ```
178
+
179
+ ### 8. View code example
180
+
181
+ **app/views/posts/show.html.haml**
182
+
183
+ ```haml
184
+ = render partial: 'the_comments/tree', locals: { commentable: @post, comments_tree: @comments }
185
+ ```
@@ -0,0 +1,58 @@
1
+ &larr; &nbsp; [documentation](documentation.md)
2
+
3
+ ### Comment API
4
+
5
+ ```ruby
6
+ @comment = Comment.last
7
+
8
+ # Comment creator, can be nil (for Guest)
9
+ @comment.user # => User
10
+
11
+ # Comment holder
12
+ # Owner of commentable object
13
+ # shouldn't be nil, should be defined on create
14
+ @comment.holder # => User
15
+
16
+ # Commentable object
17
+ @comment.commentable # => Post
18
+
19
+ # Raw user input
20
+ @comment.raw_content
21
+
22
+ # Processed user input
23
+ # method *prepare_content* should be redefined by developer
24
+ @comment.content
25
+
26
+ # Denormalization fields
27
+ @comment.commentable_title # => "Harum sint error odit."
28
+ @comment.commentable_url # => "/posts/7"
29
+ @comment.commentable_state # => "published"
30
+
31
+ # Stat info from request
32
+ # Can be used for spam detection
33
+ @comment.user_agent # => Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10
34
+ @comment.tolerance_time # => 5 (secs)
35
+ @comment.referer # => localhost:3000/post/7
36
+ @comment.ip # => 192.168.0.12
37
+
38
+ # State
39
+ @comment.state # => draft | published | deleted
40
+
41
+ # Spam flag
42
+ @comment.spam # => true
43
+
44
+ # Alias for *mark_as_spam*
45
+ @comment.to_spam
46
+
47
+ # mark this comment and all descendants as spam/not spam
48
+ @comment.mark_as_spam
49
+ @comment.mark_as_not_spam
50
+
51
+ # Comment's creator avatar
52
+ # this method can be redefined by developer
53
+ @comment.avatar_url # => "https://2.gravatar.com/avatar/015e ... 2f05?s=42&d=https://identicons.github.com/AVATAR.png"
54
+
55
+ # Anchor of comment
56
+ # this method can be redefined by developer
57
+ @comment.anchor # => b58020
58
+ ```
@@ -0,0 +1,59 @@
1
+ &larr; &nbsp; [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
+ ```
@@ -0,0 +1,27 @@
1
+ &larr; &nbsp; [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
+ &larr; &nbsp; [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
+ &larr; &nbsp; [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
+ &larr; &nbsp; [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
+ ```