commontator 0.5.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/README.md +47 -10
  2. data/Rakefile +6 -5
  3. data/app/controllers/commontator/application_controller.rb +3 -1
  4. data/app/controllers/commontator/application_controller.rb~ +5 -2
  5. data/app/controllers/commontator/comments_controller.rb +9 -10
  6. data/app/controllers/commontator/comments_controller.rb~ +9 -10
  7. data/app/controllers/commontator/commontator_controller.rb~ +22 -0
  8. data/app/controllers/commontator/subscriptions_controller.rb +2 -2
  9. data/app/controllers/commontator/subscriptions_controller.rb~ +3 -3
  10. data/app/controllers/commontator/threads_controller.rb +4 -3
  11. data/app/controllers/commontator/threads_controller.rb~ +5 -3
  12. data/app/helpers/commontator/commontator_helper.rb~ +7 -0
  13. data/app/mailers/commontator/subscriptions_mailer.rb +2 -1
  14. data/app/mailers/commontator/subscriptions_mailer.rb~ +3 -1
  15. data/app/models/commontator/comment.rb +13 -9
  16. data/app/models/commontator/comment.rb~ +14 -10
  17. data/app/models/commontator/subscription.rb +3 -3
  18. data/app/models/commontator/subscription.rb~ +19 -0
  19. data/app/models/commontator/thread.rb +17 -41
  20. data/app/models/commontator/thread.rb~ +119 -0
  21. data/app/views/commontator/shared/_thread.html.erb +4 -1
  22. data/app/views/commontator/shared/_thread.html.erb~ +5 -2
  23. data/app/views/commontator/subscriptions_mailer/comment_created_email.html.erb +1 -1
  24. data/app/views/commontator/subscriptions_mailer/comment_created_email.html.erb~ +6 -0
  25. data/config/initializers/commontator.rb +42 -64
  26. data/{test/dummy/config/initializers/commontator.rb → config/initializers/commontator.rb~} +42 -64
  27. data/db/migrate/0_install_commontator.rb +1 -1
  28. data/{test/dummy/db/migrate/1_install_commontator.commontator.rb → db/migrate/0_install_commontator.rb~} +1 -2
  29. data/lib/commontator.rb +7 -12
  30. data/lib/commontator.rb~ +7 -12
  31. data/lib/commontator/commontable_config.rb +1 -1
  32. data/lib/commontator/commontable_config.rb~ +13 -0
  33. data/lib/commontator/commontator_config.rb +1 -1
  34. data/lib/commontator/commontator_config.rb~ +13 -0
  35. data/lib/commontator/controller_includes.rb +1 -0
  36. data/lib/commontator/controller_includes.rb~ +1 -1
  37. data/lib/commontator/security_transgression.rb +3 -0
  38. data/{test/dummy/public/favicon.ico → lib/commontator/security_transgression.rb~} +0 -0
  39. data/lib/commontator/shared_helper.rb +1 -1
  40. data/lib/commontator/shared_helper.rb~ +2 -2
  41. data/lib/commontator/version.rb +1 -1
  42. data/lib/commontator/version.rb~ +1 -1
  43. metadata +46 -89
  44. data/test/commontator_test.rb +0 -7
  45. data/test/dummy/README.rdoc +0 -261
  46. data/test/dummy/Rakefile +0 -7
  47. data/test/dummy/app/assets/javascripts/application.js +0 -15
  48. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  49. data/test/dummy/app/controllers/application_controller.rb +0 -3
  50. data/test/dummy/app/helpers/application_helper.rb +0 -2
  51. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  52. data/test/dummy/config.ru +0 -4
  53. data/test/dummy/config/application.rb +0 -59
  54. data/test/dummy/config/boot.rb +0 -10
  55. data/test/dummy/config/database.yml +0 -25
  56. data/test/dummy/config/environment.rb +0 -5
  57. data/test/dummy/config/environments/development.rb +0 -37
  58. data/test/dummy/config/environments/production.rb +0 -67
  59. data/test/dummy/config/environments/test.rb +0 -37
  60. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  61. data/test/dummy/config/initializers/inflections.rb +0 -15
  62. data/test/dummy/config/initializers/mime_types.rb +0 -5
  63. data/test/dummy/config/initializers/secret_token.rb +0 -7
  64. data/test/dummy/config/initializers/session_store.rb +0 -8
  65. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  66. data/test/dummy/config/locales/en.yml +0 -5
  67. data/test/dummy/config/routes.rb +0 -4
  68. data/test/dummy/db/development.sqlite3 +0 -0
  69. data/test/dummy/db/schema.rb +0 -61
  70. data/test/dummy/log/development.log +0 -414
  71. data/test/dummy/public/404.html +0 -26
  72. data/test/dummy/public/422.html +0 -26
  73. data/test/dummy/public/500.html +0 -25
  74. data/test/dummy/script/rails +0 -6
  75. data/test/functional/comments_controller_test.rb +0 -181
  76. data/test/functional/subscriptions_controller_test.rb +0 -122
  77. data/test/integration/navigation_test.rb +0 -10
  78. data/test/test_helper.rb +0 -15
  79. data/test/unit/comment_test.rb +0 -35
  80. data/test/unit/helpers/comments_helper_test.rb +0 -4
  81. data/test/unit/helpers/subscriptions_helper_test.rb +0 -4
  82. data/test/unit/subscription_test.rb +0 -15
  83. data/test/unit/thread_test.rb +0 -57
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Commontator
2
2
 
3
3
  Commontator is a Rails engine for comments.
4
- That means it is fully functional as soon as you install and configure its gem, providing models, views and controllers of its own.
5
- At the same time, it is highly configurable, so you can change anything about it if you would like.
4
+ Being an engine means it is fully functional as soon as you install and configure its gem, providing models, views and controllers of its own.
5
+ At the same time, almost anything about it can be configured or customized to suit your needs.
6
6
 
7
7
  ## Installation
8
8
 
@@ -13,7 +13,8 @@ There are 4 steps you must follow to install commontator:
13
13
  Add this line to your application's Gemfile:
14
14
 
15
15
  ```ruby
16
- gem 'commontator', '~> 0.5.0'
16
+ gem 'commontator', '~> 0.5.0' or
17
+ gem 'commontator', '~> 1.0.0' (not yet released)
17
18
  ```
18
19
 
19
20
  And then execute:
@@ -93,6 +94,8 @@ Follow the steps below to add commontator to your models and views:
93
94
  ```
94
95
 
95
96
  Where commontable is an instance of some model that acts_as_commontable.
97
+ Note that model's record must already exist in the database, so do not use this in new.html.erb, _form.html.erb or similar.
98
+ We recommend you use this in the model's show.html.erb.
96
99
 
97
100
  3. Controllers
98
101
 
@@ -132,17 +135,51 @@ $ rake commontator:copy:models
132
135
 
133
136
  You are now free to modify them and have any changes made manifest in your application.
134
137
 
135
- ## Testing
136
-
137
- Soon
138
-
139
138
  ## Contributing
140
139
 
141
140
  1. Fork it
142
141
  2. Create your feature branch (`git checkout -b my-new-feature`)
143
- 3. Commit your changes (`git commit -am 'Added some feature'`)
144
- 4. Push to the branch (`git push origin my-new-feature`)
145
- 5. Create new Pull Request
142
+ 3. Write tests for your feature
143
+ 4. Implement your new feature
144
+ 5. Test your feature (`rake`)
145
+ 6. Commit your changes (`git commit -am 'Added some feature'`)
146
+ 7. Push to the branch (`git push origin my-new-feature`)
147
+ 8. Create new Pull Request
148
+
149
+ ## Development Environment Setup
150
+
151
+ 1. Browse to commontator's spec/dummy folder
152
+ 2. Use bundler to install all dependencies:
153
+
154
+ ```sh
155
+ $ bundle install
156
+ ```
157
+
158
+ 3. Load the schema:
159
+
160
+ ```sh
161
+ $ rake db:schema:load
162
+ ```
163
+
164
+ Or if the above fails:
165
+
166
+ ```sh
167
+ $ bundle exec rake db:schema:load
168
+ ```
169
+
170
+ ## Testing
171
+
172
+ To run all existing tests for commontator, simply execute the following from the main folder:
173
+
174
+ ```sh
175
+ $ rake
176
+ ```
177
+
178
+ Or if the above fails:
179
+
180
+ ```sh
181
+ $ bundle exec rake
182
+ ```
146
183
 
147
184
  ## License
148
185
 
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
20
  rdoc.rdoc_files.include('lib/**/*.rb')
21
21
  end
22
22
 
23
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
24
  load 'rails/tasks/engine.rake'
25
25
 
26
26
 
@@ -29,12 +29,13 @@ Bundler::GemHelper.install_tasks
29
29
 
30
30
  require 'rake/testtask'
31
31
 
32
- Rake::TestTask.new(:test) do |t|
32
+ Rake::TestTask.new(:spec) do |t|
33
+ Rake::Task['app:db:test:prepare'].invoke
33
34
  t.libs << 'lib'
34
- t.libs << 'test'
35
- t.pattern = 'test/**/*_test.rb'
35
+ t.libs << 'spec'
36
+ t.pattern = 'spec/**/*_spec.rb'
36
37
  t.verbose = false
37
38
  end
38
39
 
39
40
 
40
- task :default => :test
41
+ task :default => :spec
@@ -2,10 +2,12 @@ module Commontator
2
2
  class ApplicationController < ActionController::Base
3
3
  before_filter :get_user
4
4
 
5
+ rescue_from SecurityTransgression, :with => lambda { head(:forbidden) }
6
+
5
7
  protected
6
8
 
7
9
  def get_user
8
- @user = send Commontator.current_user_method
10
+ @user = self.send Commontator.current_user_method
9
11
  raise SecurityTransgression unless (@user.nil? || @user.is_commontator)
10
12
  end
11
13
 
@@ -2,10 +2,14 @@ module Commontator
2
2
  class ApplicationController < ActionController::Base
3
3
  before_filter :get_user
4
4
 
5
+ class SecurityTransgression < StandardError; end
6
+
7
+ rescue_from SecurityTransgression, :with => lambda { head(:forbidden) }
8
+
5
9
  protected
6
10
 
7
11
  def get_user
8
- @user = send Commontator.current_user_method
12
+ @user = self.send Commontator.current_user_method
9
13
  raise SecurityTransgression unless (@user.nil? || @user.is_commontator)
10
14
  end
11
15
 
@@ -13,7 +17,6 @@ module Commontator
13
17
  @thread = params[:thread_id].blank? ? \
14
18
  Commontator::Thread.find(params[:id]) : \
15
19
  Commontator::Thread.find(params[:thread_id])
16
- get_commontable_url
17
20
  end
18
21
 
19
22
  def get_commontable_url
@@ -13,7 +13,7 @@ module Commontator
13
13
  raise SecurityTransgression unless @comment.can_be_created_by?(@user)
14
14
 
15
15
  respond_to do |format|
16
- #format.html
16
+ format.html { redirect_to @thread }
17
17
  format.js
18
18
  end
19
19
 
@@ -29,9 +29,8 @@ module Commontator
29
29
 
30
30
  if @comment.save
31
31
  @thread.subscribe(@user) if @thread.config.auto_subscribe_on_comment
32
- @thread.mark_as_unread_except_for(@user)
32
+ @thread.add_unread_except_for(@user)
33
33
  SubscriptionsMailer.comment_created_email(@comment, @commontable_url)
34
- @thread.comment_created_callback(@user, @comment)
35
34
  else
36
35
  @errors = @comment.errors
37
36
  end
@@ -47,7 +46,7 @@ module Commontator
47
46
  raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
48
47
 
49
48
  respond_to do |format|
50
- #format.html
49
+ format.html { redirect_to @thread }
51
50
  format.js
52
51
  end
53
52
  end
@@ -55,9 +54,8 @@ module Commontator
55
54
  # PUT /comments/1
56
55
  def update
57
56
  raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
58
-
59
- @thread.comment_edited_callback(@user, @comment) \
60
- if @comment.update_attributes(params[:comment])
57
+
58
+ @comment.update_attributes(params[:comment])
61
59
 
62
60
  respond_to do |format|
63
61
  format.html { redirect_to @thread }
@@ -69,8 +67,8 @@ module Commontator
69
67
  def delete
70
68
  raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
71
69
 
72
- @comment.delete(@user)
73
- @thread.comment_deleted_callback(@user, @comment)
70
+ @comment.errors.add(:base, 'This comment has already been deleted.') \
71
+ unless @comment.delete(@user)
74
72
 
75
73
  respond_to do |format|
76
74
  format.html { redirect_to @thread }
@@ -82,7 +80,8 @@ module Commontator
82
80
  def undelete
83
81
  raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
84
82
 
85
- @comment.undelete
83
+ @comment.errors.add(:base, 'This comment is not deleted.') \
84
+ unless @comment.undelete
86
85
 
87
86
  respond_to do |format|
88
87
  format.html { redirect_to @thread }
@@ -13,7 +13,7 @@ module Commontator
13
13
  raise SecurityTransgression unless @comment.can_be_created_by?(@user)
14
14
 
15
15
  respond_to do |format|
16
- #format.html
16
+ format.html { redirect_to @thread }
17
17
  format.js
18
18
  end
19
19
 
@@ -29,9 +29,8 @@ module Commontator
29
29
 
30
30
  if @comment.save
31
31
  @thread.subscribe(@user) if @thread.config.auto_subscribe_on_comment
32
- @thread.mark_as_unread_except_for(@user)
32
+ @thread.add_unread_except_for(@user)
33
33
  SubscriptionsMailer.comment_created_email(@comment, @commontable_url)
34
- @thread.comment_created_callback(@user, @comment)
35
34
  else
36
35
  @errors = @comment.errors
37
36
  end
@@ -47,7 +46,7 @@ module Commontator
47
46
  raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
48
47
 
49
48
  respond_to do |format|
50
- format.html
49
+ format.html { redirect_to @thread }
51
50
  format.js
52
51
  end
53
52
  end
@@ -55,9 +54,8 @@ module Commontator
55
54
  # PUT /comments/1
56
55
  def update
57
56
  raise SecurityTransgression unless @comment.can_be_edited_by?(@user)
58
-
59
- @thread.comment_edited_callback(@user, @comment) \
60
- if @comment.update_attributes(params[:comment])
57
+
58
+ @comment.update_attributes(params[:comment])
61
59
 
62
60
  respond_to do |format|
63
61
  format.html { redirect_to @thread }
@@ -69,8 +67,8 @@ module Commontator
69
67
  def delete
70
68
  raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
71
69
 
72
- @comment.delete(@user)
73
- @thread.comment_deleted_callback(@user, @comment)
70
+ @comment.errors.add(:base, 'This comment has already been deleted.') \
71
+ unless @comment.delete(@user)
74
72
 
75
73
  respond_to do |format|
76
74
  format.html { redirect_to @thread }
@@ -82,7 +80,8 @@ module Commontator
82
80
  def undelete
83
81
  raise SecurityTransgression unless @comment.can_be_deleted_by?(@user)
84
82
 
85
- @comment.undelete
83
+ @comment.errors.add(:base, 'This comment is not deleted.') \
84
+ unless @comment.undelete(@user)
86
85
 
87
86
  respond_to do |format|
88
87
  format.html { redirect_to @thread }
@@ -0,0 +1,22 @@
1
+ module Commontator
2
+ class CommontatorController < ActionController::Base
3
+ before_filter :get_user
4
+
5
+ protected
6
+
7
+ def get_user
8
+ @user = ApplicationController.send Commontator.current_user_method
9
+ raise SecurityTransgression unless (@user.nil? || @user.is_commontator)
10
+ end
11
+
12
+ def get_thread
13
+ @thread = params[:thread_id].blank? ? \
14
+ Commontator::Thread.find(params[:id]) : \
15
+ Commontator::Thread.find(params[:thread_id])
16
+ end
17
+
18
+ def get_commontable_url
19
+ @commontable_url = @thread.config.commontable_url_proc.call(main_app, @thread.commontable)
20
+ end
21
+ end
22
+ end
@@ -7,7 +7,7 @@ module Commontator
7
7
  def create
8
8
  raise SecurityTransgression unless @thread.can_subscribe?(@user)
9
9
 
10
- @thread.errors.add(:base, "You are already subscribed to this thread") \
10
+ @thread.errors.add(:subscription, "You are already subscribed to this thread") \
11
11
  unless @thread.subscribe(@user)
12
12
 
13
13
  respond_to do |format|
@@ -21,7 +21,7 @@ module Commontator
21
21
  def destroy
22
22
  raise SecurityTransgression unless @thread.can_subscribe?(@user)
23
23
 
24
- @thread.errors.add(:base, "You are not subscribed to this thread") \
24
+ @thread.errors.add(:subscription, "You are not subscribed to this thread") \
25
25
  unless @thread.unsubscribe(@user)
26
26
 
27
27
  respond_to do |format|
@@ -7,11 +7,11 @@ module Commontator
7
7
  def create
8
8
  raise SecurityTransgression unless @thread.can_subscribe?(@user)
9
9
 
10
- @thread.errors.add(:base, "You are already subscribed to this thread") \
10
+ @thread.errors.add(:subscription, "You are already subscribed to this thread") \
11
11
  unless @thread.subscribe(@user)
12
12
 
13
13
  respond_to do |format|
14
- format.html { redirect_to @commontable_url }
14
+ format.html { redirect_to @thread }
15
15
  format.js { render :subscribe }
16
16
  end
17
17
 
@@ -25,7 +25,7 @@ module Commontator
25
25
  unless @thread.unsubscribe(@user)
26
26
 
27
27
  respond_to do |format|
28
- format.html { redirect_to @commontable_url }
28
+ format.html { redirect_to @thread }
29
29
  format.js { render :subscribe }
30
30
  end
31
31
  end
@@ -17,8 +17,8 @@ module Commontator
17
17
  def close
18
18
  raise SecurityTransgression unless @thread.can_be_edited_by?(@user)
19
19
 
20
- @thread.close(@user)
21
- @thread.thread_closed_callback(@user)
20
+ @thread.errors.add(:base, 'This thread has already been closed.') \
21
+ unless @thread.close(@user)
22
22
 
23
23
  respond_to do |format|
24
24
  format.html { redirect_to @thread }
@@ -30,7 +30,8 @@ module Commontator
30
30
  def reopen
31
31
  raise SecurityTransgression unless @thread.can_be_edited_by?(@user)
32
32
 
33
- @thread.reopen
33
+ @thread.errors.add(:base, 'This thread is not closed.') \
34
+ unless @thread.reopen
34
35
 
35
36
  respond_to do |format|
36
37
  format.html { redirect_to @thread }
@@ -17,8 +17,8 @@ module Commontator
17
17
  def close
18
18
  raise SecurityTransgression unless @thread.can_be_edited_by?(@user)
19
19
 
20
- @thread.close(@user)
21
- @thread.thread_closed_callback(@user)
20
+ @thread.errors.add(:base, "This thread has already been closed") \
21
+ unless @thread.close(@user)
22
22
 
23
23
  respond_to do |format|
24
24
  format.html { redirect_to @thread }
@@ -30,10 +30,12 @@ module Commontator
30
30
  def reopen
31
31
  raise SecurityTransgression unless @thread.can_be_edited_by?(@user)
32
32
 
33
- @thread.reopen
33
+ @thread.errors.add(:base, "This thread is not closed") \
34
+ unless @thread.reopen
34
35
 
35
36
  respond_to do |format|
36
37
  format.html { redirect_to @thread }
38
+ format.js { render :show }
37
39
  end
38
40
  end
39
41
  end
@@ -0,0 +1,7 @@
1
+ module Commontator
2
+ module CommontatorHelper
3
+ def javascript_proc
4
+ Commontator.javascript_proc.call(self).html_safe
5
+ end
6
+ end
7
+ end
@@ -18,7 +18,8 @@ protected
18
18
  @thread = @comment.thread
19
19
  @creator = @comment.creator
20
20
 
21
- @bcc = @thread.subscribers.reject{|s| s == @creator}\
21
+ @bcc = @thread.subscribers.reject{|s| !s.commontator_config.subscription_emails || \
22
+ s == @creator} \
22
23
  .collect{|s| commontator_email(s)}
23
24
 
24
25
  return if @bcc.empty?
@@ -1,6 +1,7 @@
1
1
  module Commontator
2
2
  class SubscriptionsMailer < ActionMailer::Base
3
3
  include SharedHelper
4
+ include ThreadsHelper
4
5
 
5
6
  def comment_created_email(comment, commontable_url)
6
7
  setup_variables(comment, commontable_url)
@@ -17,7 +18,8 @@ protected
17
18
  @thread = @comment.thread
18
19
  @creator = @comment.creator
19
20
 
20
- @bcc = @thread.subscribers.reject{|s| s == @creator}\
21
+ @bcc = @thread.subscribers.reject{|s| s == @creator || \
22
+ !s.commontator_config.subscription_emails} \
21
23
  .collect{|s| commontator_email(s)}
22
24
 
23
25
  return if @bcc.empty?
@@ -8,15 +8,16 @@ module Commontator
8
8
 
9
9
  validates_presence_of :creator, :on => :create
10
10
  validates_presence_of :thread
11
+ validates_presence_of :body
11
12
 
12
13
  attr_accessible :body
13
14
 
14
- cattr_accessor :is_votable
15
- if respond_to?(:acts_as_votable)
16
- acts_as_votable if respond_to?(:acts_as_votable)
17
- self.is_votable = true
18
- else
19
- self.is_votable = false
15
+ cattr_accessor :acts_as_votable_initialized
16
+
17
+ def is_votable?
18
+ return false unless self.class.respond_to?(:acts_as_votable)
19
+ self.class.acts_as_votable unless acts_as_votable_initialized
20
+ self.class.acts_as_votable_initialized = true
20
21
  end
21
22
 
22
23
  def is_modified?
@@ -35,12 +36,14 @@ module Commontator
35
36
  end
36
37
 
37
38
  def delete(user = nil)
39
+ return false if is_deleted?
38
40
  self.deleted_at = Time.now
39
41
  self.deleter = user
40
42
  self.save!
41
43
  end
42
44
 
43
45
  def undelete
46
+ return false unless is_deleted?
44
47
  self.deleted_at = nil
45
48
  self.save!
46
49
  end
@@ -61,20 +64,21 @@ module Commontator
61
64
 
62
65
  def can_be_edited_by?(user)
63
66
  !thread.is_closed? && !is_deleted? &&\
64
- ((user == creator && thread.config.can_edit_own_comments) ||\
67
+ ((user == creator && thread.config.can_edit_own_comments && thread.can_be_read_by?(user)) ||\
65
68
  (thread.can_be_edited_by?(user) && thread.config.admin_can_edit_comments)) &&\
66
69
  (thread.comments.last == self || thread.config.can_edit_old_comments)
67
70
  end
68
71
 
69
72
  def can_be_deleted_by?(user)
70
73
  (!thread.is_closed? &&\
71
- ((user == creator && thread.config.can_delete_own_comments) &&\
74
+ ((user == creator && thread.config.can_delete_own_comments && \
75
+ thread.can_be_read_by?(user) && (!is_deleted? || deleter == user)) &&\
72
76
  (thread.comments.last == self || thread.config.can_delete_old_comments))) ||\
73
77
  thread.can_be_edited_by?(user)
74
78
  end
75
79
 
76
80
  def can_be_voted_on?
77
- is_votable && !is_deleted? && thread.config.comments_can_be_voted_on
81
+ is_votable? && !is_deleted? && thread.config.can_vote_on_comments
78
82
  end
79
83
 
80
84
  def can_be_voted_on_by?(user)