adva_comments 0.1.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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +2 -0
  7. data/adva_comments.gemspec +20 -0
  8. data/app/assets/javascripts/adva_comments/jquery.comments.js +41 -0
  9. data/app/assets/stylesheets/adva_comments/admin/comments.scss +34 -0
  10. data/app/assets/stylesheets/adva_comments/comments.scss +50 -0
  11. data/app/controllers/admin/comments_controller.rb +86 -0
  12. data/app/controllers/comments_controller.rb +109 -0
  13. data/app/helpers/admin/comments_helper.rb +32 -0
  14. data/app/helpers/comments_helper.rb +71 -0
  15. data/app/mailers/comment_mailer.rb +8 -0
  16. data/app/models/comment.rb +94 -0
  17. data/app/views/admin/articles/_comments_settings.html.erb +1 -0
  18. data/app/views/admin/comments/_form.html.erb +12 -0
  19. data/app/views/admin/comments/edit.html.erb +9 -0
  20. data/app/views/admin/comments/index.html.erb +43 -0
  21. data/app/views/admin/sections/_comments_settings.html.erb +7 -0
  22. data/app/views/admin/sites/_comments_settings.html.erb +7 -0
  23. data/app/views/comment_mailer/comment_notification.html.erb +12 -0
  24. data/app/views/comments/_comment.html.erb +13 -0
  25. data/app/views/comments/_form.html.erb +44 -0
  26. data/app/views/comments/_list.html.erb +8 -0
  27. data/app/views/comments/comments.atom.builder +16 -0
  28. data/app/views/comments/preview.html.erb +3 -0
  29. data/app/views/comments/show.html.erb +12 -0
  30. data/config/initializers/article.rb +13 -0
  31. data/config/initializers/content.rb +17 -0
  32. data/config/initializers/controllers.rb +25 -0
  33. data/config/initializers/menus.rb +24 -0
  34. data/config/initializers/section.rb +15 -0
  35. data/config/initializers/site.rb +11 -0
  36. data/config/routes.rb +9 -0
  37. data/db/migrate/20080401000007_create_comments_table.rb +22 -0
  38. data/db/migrate/20080721141112_add_comment_board_id.rb +9 -0
  39. data/lib/action_controller/acts_as_commentable.rb +43 -0
  40. data/lib/active_record/has_many_comments.rb +49 -0
  41. data/lib/adva_comments/version.rb +3 -0
  42. data/lib/adva_comments.rb +19 -0
  43. data/lib/format.rb +3 -0
  44. data/test/contexts.rb +29 -0
  45. data/test/functional/admin/comments_controller_test.rb +200 -0
  46. data/test/functional/comments_controller_test.rb +133 -0
  47. data/test/functional/comments_routes_test.rb +17 -0
  48. data/test/test_helper.rb +4 -0
  49. data/test/unit/helpers/admin/comments_helper_test.rb +23 -0
  50. data/test/unit/helpers/comments_helper_test.rb +147 -0
  51. data/test/unit/models/comment_test.rb +150 -0
  52. data/test/unit/models/commentable_test.rb +30 -0
  53. data/test/unit/observers/activities_comment_observer_test.rb +45 -0
  54. metadata +132 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e97b4790dbbafc5bd5a7b1587994a0376996f0afbfaa066105f48be741a60c39
4
+ data.tar.gz: 7c89022fc00fd8ce186d011b2d7b0e732094613e7d2f410f9be8f01e6a8b0fa0
5
+ SHA512:
6
+ metadata.gz: b791d5fa817b56fe2ffd25ea6fbfcb150ec3e89506b17199e2234895442d36d134be438897878b915982e77631d995a0b6409b7e395f601fca0ee866a7e5ebc2
7
+ data.tar.gz: 0a5b0ad8cd654fc989e41d19616ffa513502132272238eb81b9a5eca98aa76074d51f88abc73ba6d0ac4e1f32921b153f3a90530294c86933615ae931fdcd92e
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in adva_comments.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Micah Geisel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # AdvaComments
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'adva_comments'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install adva_comments
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/adva_comments/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Micah Geisel"]
6
+ gem.email = ["micah@botandrose.com"]
7
+ gem.description = %q{Adva Comments}
8
+ gem.summary = %q{Engine for Adva CMS commenting component}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "adva_comments"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = AdvaComments::VERSION
17
+
18
+ gem.add_dependency "validates_email_format_of"
19
+ gem.add_dependency "invisible_captcha"
20
+ end
@@ -0,0 +1,41 @@
1
+ var CommentForm = {
2
+ init: function() {
3
+ var user_name = Cookie.get('uname');
4
+ if (user_name) {
5
+ user_name = unescape(user_name).replace(/\+/g, " ");
6
+ try { $('#registered_author span').each(function() { $(this).html(user_name); }); } catch(err) {}
7
+ try { $('#registered_author').show(); } catch(err) {}
8
+ try { $('#anonymous_author').hide(); } catch(err) {}
9
+ }
10
+ }
11
+ };
12
+
13
+ var Comment = {
14
+ preview: function(event) {
15
+ event.preventDefault();
16
+ $.ajax({
17
+ url: this.href,
18
+ type: 'post',
19
+ dataType: 'html',
20
+ data: $('form#comment_form').serializeArray(),
21
+ success: function(data, status) {
22
+ $('#preview').html(data);
23
+ },
24
+ beforeSend: function(xhr) {
25
+ $('#comment_preview_spinner').show();
26
+ },
27
+ complete: function(xhr, status) {
28
+ $('#comment_preview_spinner').hide();
29
+ }
30
+ });
31
+ }
32
+ }
33
+
34
+ $(document).ready(function() {
35
+ if($('#anonymous_author')) {
36
+ CommentForm.init();
37
+ }
38
+
39
+ $('a#preview_comment').show();
40
+ $('a#preview_comment').click(Comment.preview);
41
+ });
@@ -0,0 +1,34 @@
1
+ #comments_list {
2
+ list-style-type: none;
3
+ margin: 0;
4
+ padding: 0;
5
+ }
6
+ #comments_list li {
7
+ margin-top: 15px;
8
+ padding: 0 40px 0 25px;
9
+ background: image_url("adva_cms/icons/comment.png") no-repeat left 3px;
10
+ }
11
+ #comments_list li.highlight {
12
+ padding: 20px 20px 20px 55px !important;
13
+ padding-bottom: 3px;
14
+ border: 1px solid #add;
15
+ background-color: #eaf6f6 !important;
16
+ margin: 20px 0;
17
+ }
18
+ #comments_list .actions {
19
+ float: right;
20
+ margin-top: -1px;
21
+ height: 20px;
22
+ line-height: 20px;
23
+ overflow: hidden;
24
+ }
25
+ #comments_list .actions a {
26
+ margin-top: -2px;
27
+ }
28
+ #comments_list blockquote {
29
+ margin: 0;
30
+ }
31
+ #comments_list cite {
32
+ font-size: 12px;
33
+ font-style: normal;
34
+ }
@@ -0,0 +1,50 @@
1
+ /* COMMENTS */
2
+
3
+ #comments {
4
+ padding-bottom: 9px;
5
+ }
6
+ #comments h3 {
7
+ font-size: 18px;
8
+ line-height: 18px;
9
+ margin: 18px 0 18px 0;
10
+ }
11
+ #comments ol {
12
+ list-style-type: none;
13
+ margin-left: 0;
14
+ }
15
+ #comments ol li {
16
+ padding-bottom: 17px;
17
+ margin-bottom: 18px;
18
+ border-bottom: 1px solid #bbb;
19
+ }
20
+ #comments .meta p {
21
+ margin: 0;
22
+ }
23
+ #comments .comment {
24
+ padding-left: 220px;
25
+ }
26
+
27
+ /* COMMENTS FORM */
28
+
29
+ #comment_form_wrapper {
30
+ padding-left: 220px;
31
+ padding-bottom: 9px;
32
+ margin-bottom: 26px;
33
+ border-bottom: 1px solid #bbb;
34
+ }
35
+ #comment_user {
36
+ float: right;
37
+ margin-top: 3px;
38
+ }
39
+ #comment_form label {
40
+ display: block;
41
+ float: left;
42
+ width: 100px;
43
+ }
44
+ #comment_form input {
45
+ width: 180px;
46
+ }
47
+ #comment_form textarea {
48
+ height: 150px;
49
+ width: 99%;
50
+ }
@@ -0,0 +1,86 @@
1
+ class Admin::CommentsController < Admin::BaseController
2
+ layout "admin"
3
+
4
+ before_action :set_comment, :only => [:edit, :update, :destroy]
5
+ before_action :set_commentable, :set_comment_params, :only => :create
6
+ after_action :postback_spaminess, :only => [:update]
7
+
8
+ def index
9
+ # FIXME how to remove the Topic dependency here?
10
+ # maybe make Comment a subclass of Comment::Base or something so that we can use STI to exclude
11
+ # special comment types?
12
+ @comments = @site.comments.where(['commentable_type NOT IN (?)', 'Topic']).
13
+ reorder("comments.created_at DESC").
14
+ paginate(:page => current_page, :per_page => 25)
15
+ end
16
+
17
+ def edit
18
+ end
19
+
20
+ def update
21
+ if @comment.update params[:comment]
22
+ trigger_events @comment
23
+ flash[:notice] = t(:'adva.comments.flash.update.success')
24
+ redirect_to params[:return_to] || admin_comments_url
25
+ else
26
+ flash.now[:error] = t(:'adva.comments.flash.update.failure')
27
+ render :action => :edit
28
+ end
29
+ end
30
+
31
+ def destroy
32
+ @comment.destroy
33
+ trigger_events @comment
34
+ flash[:notice] = t(:'adva.comments.flash.destroy.success')
35
+ redirect_to params[:return_to] || admin_comments_url
36
+ end
37
+
38
+ private
39
+
40
+ def set_menu
41
+ @menu = Menus::Admin::Comments.new
42
+ end
43
+
44
+ def set_commentable
45
+ type, id = params[:comment].values_at(:commentable_type, :commentable_id)
46
+ @commentable = type.constantize.find id
47
+ end
48
+
49
+ def set_comment_params
50
+ params[:comment].merge! :site_id => @commentable.site_id,
51
+ :section_id => @commentable.section_id,
52
+ :author => current_user
53
+ end
54
+
55
+ def set_comment
56
+ @comment = Comment.find(params[:id])
57
+ end
58
+
59
+ def filter_options options
60
+ case params[:filter]
61
+ when 'state'
62
+ params[:state] == 'approved' ? options[:conditions] = "approved = '1'" : options[:conditions] = "approved = '0'"
63
+ when 'body'
64
+ options[:conditions] = Comment.send(:sanitize_sql, ["LOWER(body) LIKE :query", {:query => "%#{params[:query].downcase}%"}])
65
+ when 'author_name'
66
+ options[:conditions] = Comment.send(:sanitize_sql, ["LOWER(author_name) LIKE :query", {:query => "%#{params[:query].downcase}%"}])
67
+ when 'author_email'
68
+ options[:conditions] = Comment.send(:sanitize_sql, ["LOWER(author_email) LIKE :query", {:query => "%#{params[:query].downcase}%"}])
69
+ when 'author_homepage'
70
+ options[:conditions] = Comment.send(:sanitize_sql, ["LOWER(author_homepage) LIKE :query", {:query => "%#{params[:query].downcase}%"}])
71
+ end
72
+ options
73
+ end
74
+
75
+ def postback_spaminess
76
+ if @comment.approved_changed? and @site.respond_to?(:spam_engine)
77
+ spaminess = @comment.approved? ? :ham : :spam
78
+ @site.spam_engine.mark_spaminess(spaminess, @comment, :url => show_url(@comment.commentable))
79
+ end
80
+ end
81
+
82
+ def current_resource
83
+ @comment ? @comment.commentable : @content || @section || @site
84
+ end
85
+ end
86
+
@@ -0,0 +1,109 @@
1
+ class CommentsController < BaseController
2
+ # TODO apparently it is not possible to use protect_from_forgery with
3
+ # page cached forms? is that correct? as protect_from_forgery seems to
4
+ # validate the form token against the session and ideally when all pages
5
+ # and assets are cached there is no session at all this seems to make sense.
6
+ #
7
+ # Rails docs say: "done by embedding a token based on the session ... in all
8
+ # forms and Ajax requests generated by Rails and then verifying the authenticity
9
+ # of that token in the controller"
10
+ # http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html
11
+ #
12
+ # Note: Could fetch forgery token via AJAX?
13
+
14
+ protect_from_forgery :except => [:preview, :create]
15
+
16
+ authenticates_anonymous_user
17
+ layout 'default'
18
+
19
+ before_action :set_section
20
+ before_action :set_comment, :only => [:show, :update, :destroy]
21
+ before_action :set_commentable, :only => [:show, :preview, :create]
22
+
23
+ invisible_captcha only: [:create, :update], honeypot: :subtitle, if: -> { current_user.anonymous? }
24
+
25
+ def show
26
+ end
27
+
28
+ def preview
29
+ @comment = @commentable.comments.build(comment_params)
30
+ @comment.send(:process_filters)
31
+ render :layout => false
32
+ end
33
+
34
+ def create
35
+ @comment = @commentable.comments.build(comment_params)
36
+ if @comment.save
37
+ trigger_events @comment
38
+ CommentMailer.comment_notification(@comment).deliver_later
39
+ if current_user.anonymous?
40
+ flash.notice = "Your comment is being reviewed, and will be posted shortly. Thank you for commenting!"
41
+ else
42
+ @comment.update_column :approved, true
43
+ flash.notice = "You're an admin, so your comment is being posted immediately! Refresh the page to see it."
44
+ end
45
+ respond_to do |format|
46
+ format.html { redirect_to "#{request.env['HTTP_REFERER']}#comments" }
47
+ format.js { render json: true }
48
+ end
49
+ else
50
+ flash[:error] = @comment.errors.full_messages.to_sentence # TODO hu.
51
+ respond_to do |format|
52
+ format.html { redirect_to "#{request.env['HTTP_REFERER']}#comments" }
53
+ format.js { render json: false }
54
+ end
55
+ end
56
+ end
57
+
58
+ def update
59
+ if @comment.update(comment_params)
60
+ trigger_events(@comment)
61
+ flash.notice = t(:'adva.comments.flash.update.success')
62
+ render json: true
63
+ else
64
+ set_commentable
65
+ flash[:error] = @comment.errors.full_messages.to_sentence
66
+ render json: false
67
+ end
68
+ end
69
+
70
+ def destroy
71
+ @comment.destroy
72
+ trigger_events @comment
73
+ redirect_to "/", notice: t(:'adva.comments.flash.destroy.success')
74
+ end
75
+
76
+ protected
77
+
78
+ def comment_params
79
+ params.require(:comment).permit(
80
+ :author_email,
81
+ :author_name,
82
+ :body,
83
+ :commentable_id,
84
+ :commentable_type,
85
+ ).merge(site_id: @commentable.site_id, section_id: @commentable.section_id)
86
+ end
87
+
88
+ def set_comment
89
+ @comment = Comment.find(params[:id])
90
+ end
91
+
92
+ def set_commentable
93
+ @commentable = if @comment
94
+ @comment.commentable or raise ActiveRecord::RecordNotFound
95
+ else
96
+ begin
97
+ klass = params.dig(:comment, :commentable_type).constantize
98
+ raise NameError unless klass.has_many_comments?
99
+ rescue NameError
100
+ raise ActiveRecord::RecordNotFound
101
+ end
102
+ klass.find(params.dig(:comment, :commentable_id))
103
+ end
104
+ end
105
+
106
+ def current_resource
107
+ @comment || @commentable
108
+ end
109
+ end
@@ -0,0 +1,32 @@
1
+ module Admin
2
+ module CommentsHelper
3
+ def comment_expiration_options
4
+ I18n.with_options :scope => :'adva.comments.options.expiration' do |i18n|
5
+ [ [i18n.t(:not_allowed), -1 ],
6
+ [i18n.t(:never_expire), 0 ],
7
+ [i18n.t(:x_hours_after_publishing, :count => 24), 1 ],
8
+ [i18n.t(:x_weeks_after_publishing, :count => 1), 7 ],
9
+ [i18n.t(:x_months_after_publishing, :count => 1), 30],
10
+ [i18n.t(:x_months_after_publishing, :count => 3), 90] ]
11
+ end
12
+ end
13
+
14
+ def comments_filter_options
15
+ options = I18n.t(:'adva.comments.filter.options')
16
+
17
+ [[options[:all], 'all'],
18
+ [options[:state], 'state'],
19
+ [options[:body], 'body'],
20
+ [options[:author_name], 'author_name'],
21
+ [options[:author_email], 'author_email'],
22
+ [options[:author_url], 'author_homepage']]
23
+ end
24
+
25
+ def comments_state_options
26
+ options = I18n.t(:'adva.comments.state.options')
27
+
28
+ [[options[:approved], 'approved'],
29
+ [options[:unapproved], 'unapproved']]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,71 @@
1
+ module CommentsHelper
2
+ def comments_feed_title(*owners)
3
+ options = owners.extract_options!
4
+ separator = options[:separator] || ' &raquo; '
5
+ I18n.t(:'adva.titles.comments') + ': ' + owners.compact.uniq.map(&:title).join(separator)
6
+ end
7
+
8
+ methods = %w(admin_comments_path admin_comment_path
9
+ new_admin_comment_path edit_admin_comment_path)
10
+
11
+ methods.each do |method|
12
+ module_eval <<-CODE, __FILE__, __LINE__
13
+ def #{method}(*args)
14
+ options = args.extract_options!
15
+ merge_admin_comments_query_params(options)
16
+ super *(args << options).compact
17
+ end
18
+ CODE
19
+ end
20
+
21
+ def link_to_content_comments_count(content, options = {:total => true})
22
+ total = content.comments_count
23
+ approved = content.approved_comments_count
24
+ return options[:alt] || t(:'adva.common.none') if approved == 0
25
+ text = if total == approved or !options[:total]
26
+ "#{approved.to_s.rjust(2, '0')}"
27
+ else
28
+ "#{approved.to_s.rjust(2, '0')} (#{total.to_s.rjust(2, '0')})"
29
+ end
30
+ link_to_content_comments(text, content)
31
+ end
32
+
33
+ def link_to_content_comments(*args)
34
+ options = args.extract_options!
35
+ text = args.shift if args.first.is_a?(String) || args.first.is_a?(Symbol)
36
+ content, comment = *args
37
+ return unless content.approved_comments_count > 0 || content.accept_comments?
38
+
39
+ text = t(text) if text.is_a?(Symbol)
40
+ text ||= t(:'adva.comments.titles.comment_with_count', :count => content.approved_comments_count)
41
+ options.merge! :anchor => (comment ? dom_id(comment) : 'comments')
42
+ link_to text, [content.section, content], options
43
+ end
44
+
45
+ def link_to_content_comment(*args)
46
+ options = args.extract_options!
47
+ args.insert(args.size - 1, args.last.commentable)
48
+ link_to_content_comments(*args << options)
49
+ end
50
+
51
+ def link_to_remote_comment_preview
52
+ link_to(I18n.t(:'adva.titles.preview'), preview_comments_path, :id => 'preview_comment', :style => "display:none;") +
53
+ image_tag('adva_cms/indicator.gif', :alt => '', :id => 'comment_preview_spinner', :style => 'display:none;')
54
+ end
55
+
56
+ def comment_form_hidden_fields(commentable)
57
+ hidden_field_tag('return_to', request.fullpath) + "\n" +
58
+ hidden_field_tag('comment[commentable_type]', commentable.class.name, :id => 'comment_commentable_type') + "\n" +
59
+ hidden_field_tag('comment[commentable_id]', commentable.id, :id => 'comment_commentable_id') + "\n"
60
+ end
61
+
62
+ private
63
+
64
+ # TODO obviously doesn't work as expected on the SectionsController where the
65
+ # section_id is in params[:id]
66
+ def merge_admin_comments_query_params(options)
67
+ options.merge! params.slice(:section_id, :content_id).reject{|key, value| value.blank? }.to_unsafe_hash
68
+ options.symbolize_keys!
69
+ options.delete(:section_id) if options[:content_id]
70
+ end
71
+ end
@@ -0,0 +1,8 @@
1
+ class CommentMailer < ActionMailer::Base
2
+ default :content_type => "text/html"
3
+
4
+ def comment_notification comment
5
+ @comment = comment
6
+ mail :to => comment.site.email, :from => comment.site.email, :subject => "#{comment.site.name}: New pending comment"
7
+ end
8
+ end
@@ -0,0 +1,94 @@
1
+ class Comment < ActiveRecord::Base
2
+ class CommentNotAllowed < StandardError; end
3
+
4
+ def self.approved
5
+ where :approved => true
6
+ end
7
+
8
+ def self.unapproved
9
+ where :approved => false
10
+ end
11
+
12
+ define_model_callbacks :approve, :unapprove
13
+
14
+ def around_save
15
+ if just_approved?
16
+ run_callbacks(:approve) { yield }
17
+ elsif just_unapproved?
18
+ run_callbacks(:unapprove) { yield }
19
+ else
20
+ yield
21
+ end
22
+ end
23
+
24
+ after_save do
25
+ commentable.touch
26
+ end
27
+
28
+ filtered_column :body
29
+ filters_attributes :sanitize => :body_html
30
+
31
+ has_filter :text => { :attributes => [:body] },
32
+ :state => { :states => [:approved, :unapproved] }
33
+
34
+ belongs_to :site
35
+ belongs_to :section
36
+ belongs_to :commentable, :polymorphic => true
37
+ # make sure we're storing the base clase for STI
38
+ def commentable_type=(sType)
39
+ super(sType.to_s.classify.constantize.base_class.to_s)
40
+ end
41
+ has_many :activities, :as => :object
42
+
43
+ composed_of :author, :class_name => "User", :mapping => [ %w(author_name name), %w(author_email email) ]
44
+
45
+ validates_presence_of :body, :commentable, :author_name, :author_email
46
+ validates_email_format_of :author_email
47
+
48
+ before_validation :set_owners
49
+ before_create :authorize_commenting
50
+
51
+ def owner
52
+ commentable
53
+ end
54
+
55
+ def filter
56
+ commentable.comment_filter
57
+ end
58
+
59
+ def unapproved?
60
+ !approved?
61
+ end
62
+
63
+ def just_approved?
64
+ approved_changed? and approved?
65
+ end
66
+
67
+ def just_unapproved?
68
+ approved_changed? and unapproved?
69
+ end
70
+
71
+ def state_changes
72
+ state_changes = if just_approved?
73
+ [:approved]
74
+ elsif just_unapproved?
75
+ [:unapproved]
76
+ end || []
77
+ super + state_changes
78
+ end
79
+
80
+ protected
81
+
82
+ def authorize_commenting
83
+ if commentable && !commentable.accept_comments?
84
+ raise CommentNotAllowed, I18n.t(:'adva.comments.messages.not_allowed')
85
+ end
86
+ end
87
+
88
+ def set_owners
89
+ if commentable # TODO in what cases would commentable be nil here?
90
+ self.site = commentable.site
91
+ self.section = commentable.section
92
+ end
93
+ end
94
+ end
@@ -0,0 +1 @@
1
+ <%= f.select(:comment_age, comment_expiration_options, {}, :label => :'adva.titles.comments') %>
@@ -0,0 +1,12 @@
1
+ <%= hidden_field_tag "return_to", params[:return_to] || request.request_uri %>
2
+
3
+ <% f.field_set do %>
4
+ <%= f.text_area :body, :rows => 8, :label => :'adva.titles.comment' %>
5
+ <% end %>
6
+
7
+ <%= yield if block_given? %>
8
+
9
+ <% f.buttons do %>
10
+ <%= submit_tag t(:'adva.common.save') %>
11
+ <%= link_to t(:'adva.common.cancel'), params[:return_to] if params[:return_to] %>
12
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <h3><%= t(:'adva.comments.titles.edit') %></h3>
2
+
3
+ <%= form_for [:admin, @comment] do |f| -%>
4
+ <% render :layout => 'form', :locals => {:f => f} do %>
5
+ <p>
6
+ <label><%= f.check_box :approved, {}, 1 %><%= t(:'adva.comments.labels.approved') %></label>
7
+ </p>
8
+ <% end -%>
9
+ <% end -%>