message_train 0.6.17 → 0.7.1

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +16 -13
  3. data/.rubocop_todo.yml +12 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +1 -1
  6. data/Gemfile +28 -30
  7. data/README.md +284 -0
  8. data/Rakefile +6 -7
  9. data/VERSION +1 -1
  10. data/app/assets/javascripts/ckeditor/{config.js.coffee → config.js} +7 -6
  11. data/app/assets/stylesheets/message_train.scss +0 -8
  12. data/app/controllers/concerns/message_train_authorization.rb +37 -0
  13. data/app/controllers/concerns/message_train_support.rb +41 -69
  14. data/app/controllers/message_train/application_controller.rb +1 -0
  15. data/app/controllers/message_train/boxes_controller.rb +5 -4
  16. data/app/controllers/message_train/conversations_controller.rb +7 -5
  17. data/app/controllers/message_train/messages_controller.rb +43 -27
  18. data/app/controllers/message_train/participants_controller.rb +14 -25
  19. data/app/controllers/message_train/unsubscribes_controller.rb +96 -61
  20. data/app/helpers/message_train/application_helper.rb +13 -7
  21. data/app/helpers/message_train/attachments_helper.rb +4 -12
  22. data/app/helpers/message_train/boxes_helper.rb +4 -14
  23. data/app/helpers/message_train/collectives_helper.rb +23 -29
  24. data/app/helpers/message_train/conversations_helper.rb +52 -30
  25. data/app/helpers/message_train/messages_helper.rb +33 -20
  26. data/app/mailers/message_train/receipt_mailer.rb +22 -12
  27. data/app/models/message_train/attachment.rb +2 -2
  28. data/app/models/message_train/box.rb +182 -228
  29. data/app/models/message_train/conversation.rb +100 -103
  30. data/app/models/message_train/ignore.rb +83 -4
  31. data/app/models/message_train/message.rb +66 -117
  32. data/app/models/message_train/receipt.rb +73 -49
  33. data/app/views/message_train/boxes/show.html.haml +11 -7
  34. data/config/locales/en.yml +1 -0
  35. data/config/routes.rb +6 -12
  36. data/lib/message_train.rb +3 -1
  37. data/lib/message_train/class_methods.rb +51 -0
  38. data/lib/message_train/configuration.rb +28 -3
  39. data/lib/message_train/instance_methods.rb +209 -0
  40. data/lib/message_train/mixin.rb +25 -320
  41. data/message_train.gemspec +83 -83
  42. data/spec/controllers/message_train/boxes_controller_spec.rb +37 -19
  43. data/spec/controllers/message_train/concerns_spec.rb +21 -3
  44. data/spec/controllers/message_train/conversations_controller_spec.rb +41 -18
  45. data/spec/controllers/message_train/messages_controller_spec.rb +112 -31
  46. data/spec/controllers/message_train/participants_controller_spec.rb +33 -7
  47. data/spec/controllers/message_train/unsubscribes_controller_spec.rb +10 -8
  48. data/spec/dummy/app/assets/stylesheets/{application.css.scss → application.scss} +2 -1
  49. data/spec/dummy/app/assets/stylesheets/bootstrap-everything.scss +54 -0
  50. data/spec/dummy/app/models/group.rb +1 -1
  51. data/spec/dummy/app/views/layouts/application.html.haml +9 -8
  52. data/spec/dummy/bin/setup +8 -8
  53. data/spec/dummy/config/application.rb +0 -3
  54. data/spec/dummy/config/environments/test.rb +4 -2
  55. data/spec/dummy/db/schema.rb +94 -103
  56. data/spec/dummy/db/test.sqlite3 +0 -0
  57. data/spec/factories/attachment.rb +3 -1
  58. data/spec/factories/message.rb +2 -3
  59. data/spec/features/boxes_spec.rb +0 -3
  60. data/spec/helpers/message_train/application_helper_spec.rb +3 -2
  61. data/spec/helpers/message_train/attachment_helper_spec.rb +4 -0
  62. data/spec/helpers/message_train/boxes_helper_spec.rb +1 -0
  63. data/spec/helpers/message_train/collectives_helper_spec.rb +1 -0
  64. data/spec/helpers/message_train/conversations_helper_spec.rb +3 -2
  65. data/spec/helpers/message_train/messages_helper_spec.rb +2 -1
  66. data/spec/models/group_spec.rb +6 -4
  67. data/spec/models/message_train/box_spec.rb +0 -88
  68. data/spec/models/message_train/ignore_spec.rb +65 -0
  69. data/spec/models/message_train/message_spec.rb +6 -5
  70. data/spec/models/message_train/receipt_spec.rb +6 -8
  71. data/spec/models/role_spec.rb +2 -2
  72. data/spec/models/user_spec.rb +29 -101
  73. data/spec/rails_helper.rb +16 -30
  74. data/spec/support/feature_behaviors.rb +2 -1
  75. data/spec/support/shared_connection.rb +5 -0
  76. data/spec/support/utilities.rb +7 -8
  77. metadata +145 -120
  78. data/README.rdoc +0 -175
  79. data/spec/dummy/app/models/.keep +0 -0
  80. data/spec/dummy/log/.keep +0 -0
data/Rakefile CHANGED
@@ -10,21 +10,20 @@ rescue Bundler::BundlerError => e
10
10
  end
11
11
  require 'rake'
12
12
 
13
- require 'jeweler'
14
- Jeweler::Tasks.new do |gem|
13
+ require 'juwelier'
14
+ Juwelier::Tasks.new do |gem|
15
15
  # gem is a Gem::Specification...
16
16
  # see http://guides.rubygems.org/specification-reference/ for more options
17
17
  gem.name = 'message_train'
18
18
  gem.homepage = 'http://www.gemvein.com/museum/cases/message_train'
19
19
  gem.license = 'MIT'
20
- gem.summary = 'Rails 4 Engine providing messaging for any object'
21
- gem.description = 'Rails 4 Engine providing private/public messaging for '\
22
- 'any object, such as Users or Groups'
20
+ gem.summary = 'Rails 4 & 5 Engine providing messaging for any object'
21
+ gem.description = 'Rails 4 & 5 Engine providing private and public messaging'\
22
+ ' for any object, such as Users or Groups'
23
23
  gem.email = 'karen.e.lundgren@gmail.com'
24
24
  gem.authors = ['Karen Lundgren']
25
- # dependencies defined in Gemfile
26
25
  end
27
- Jeweler::RubygemsDotOrgTasks.new
26
+ Juwelier::RubygemsDotOrgTasks.new
28
27
 
29
28
  require 'rspec/core'
30
29
  require 'rspec/core/rake_task'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.17
1
+ 0.7.1
@@ -1,6 +1,6 @@
1
- CKEDITOR.editorConfig = (config) ->
2
- config.allowedContent = true
3
- config.width = '100%'
1
+ CKEDITOR.editorConfig = function(config) {
2
+ config.allowedContent = true;
3
+ config.width = '100%';
4
4
  config.toolbar_full = [
5
5
  {
6
6
  name: 'links',
@@ -43,6 +43,7 @@ CKEDITOR.editorConfig = (config) ->
43
43
  'RemoveFormat'
44
44
  ]
45
45
  }
46
- ]
47
- config.toolbar = 'full'
48
- true
46
+ ];
47
+ config.toolbar = 'full';
48
+ return true;
49
+ };
@@ -82,20 +82,12 @@ div.conversation-actions {
82
82
 
83
83
  td.conversation-actions {
84
84
  white-space: nowrap;
85
-
86
- a {
87
- visibility: hidden;
88
- }
89
85
  }
90
86
 
91
87
  .date-column {
92
88
  white-space: nowrap;
93
89
  }
94
90
 
95
- tr:hover .conversation-actions a {
96
- visibility: visible;
97
- }
98
-
99
91
  .glyphicon-thumbnail {
100
92
  font-size: 170px;
101
93
  }
@@ -0,0 +1,37 @@
1
+ # MessageTrain authorization
2
+ module MessageTrainAuthorization
3
+ extend ActiveSupport::Concern
4
+
5
+ protected
6
+
7
+ def authorize_collective(collective, division)
8
+ return false unless authorize_collective_access(collective)
9
+ case division
10
+ when :in, :ignored
11
+ authorize_collective_receiving(collective)
12
+ when :sent, :drafts
13
+ authorize_collective_sending(collective)
14
+ end
15
+ end
16
+
17
+ def authorize_collective_access(collective)
18
+ return true if collective.allows_access_by? @box_user
19
+ flash[:error] = :access_to_that_box_denied.l
20
+ redirect_to main_app.root_url
21
+ false
22
+ end
23
+
24
+ def authorize_collective_receiving(collective)
25
+ return true if collective.allows_receiving_by? @box_user
26
+ flash[:error] = :access_to_that_box_denied.l
27
+ redirect_to message_train.collective_box_url(collective.path_part, :sent)
28
+ false
29
+ end
30
+
31
+ def authorize_collective_sending(collective)
32
+ return true if collective.allows_sending_by? @box_user
33
+ flash[:error] = :access_to_that_box_denied.l
34
+ redirect_to message_train.collective_box_url(collective.path_part, :in)
35
+ false
36
+ end
37
+ end
@@ -3,13 +3,13 @@ module MessageTrainSupport
3
3
  extend ActiveSupport::Concern
4
4
  included do
5
5
  # Last in first out
6
- prepend_before_filter :load_collective_boxes,
6
+ prepend_before_action :load_collective_boxes,
7
7
  :load_box,
8
8
  :load_collective,
9
9
  :load_division,
10
10
  :load_box_user,
11
11
  unless: :devise_controller?
12
- before_filter :load_objects
12
+ before_action :load_objects
13
13
  before_action :set_locale
14
14
 
15
15
  helper MessageTrain::ApplicationHelper
@@ -24,6 +24,11 @@ module MessageTrainSupport
24
24
  end
25
25
  end
26
26
 
27
+ def redirect_to_sign_in
28
+ flash[:error] = :you_must_sign_in_or_sign_up_to_continue.l
29
+ redirect_to MessageTrain.configuration.user_sign_in_path
30
+ end
31
+
27
32
  protected
28
33
 
29
34
  def anonymous
@@ -36,9 +41,8 @@ module MessageTrainSupport
36
41
  end
37
42
 
38
43
  def load_box_user
39
- @box_user = send(
40
- MessageTrain.configuration.current_user_method
41
- ) || anonymous
44
+ @box_user = send(MessageTrain.configuration.current_user_method)
45
+ @box_user ||= anonymous
42
46
  end
43
47
 
44
48
  def load_division
@@ -46,45 +50,15 @@ module MessageTrainSupport
46
50
  end
47
51
 
48
52
  def load_collective
49
- if params[:collective_id].present?
50
- collective_table, collective_id = params[:collective_id].split(':')
51
- collective_class_name = MessageTrain.configuration.recipient_tables[
52
- collective_table.to_sym
53
- ]
54
- collective_model = collective_class_name.constantize
55
- slug_column = MessageTrain.configuration
56
- .slug_columns[collective_table.to_sym] || :slug
57
- @collective = collective_model.find_by!(slug_column => collective_id)
58
-
59
- unless @collective.allows_receiving_by?(
60
- @box_user
61
- ) || @collective.allows_sending_by?(
62
- @box_user
63
- )
64
- flash[:error] = :access_to_that_box_denied.l
65
- redirect_to main_app.root_url
66
- return
67
- end
53
+ return unless params[:collective_id].present?
54
+ collective_table, collective_id = params[:collective_id].split(':')
55
+ model = get_collective_model(collective_table)
56
+ @collective = model.find_by!(model.slug_column => collective_id)
57
+ authorize_collective(@collective, @division)
58
+ end
68
59
 
69
- case @division
70
- when :in, :ignored
71
- unless @collective.allows_receiving_by? @box_user
72
- flash[:error] = :access_to_that_box_denied.l
73
- redirect_to message_train.collective_box_url(
74
- @collective.path_part,
75
- :sent
76
- )
77
- end
78
- when :sent, :drafts
79
- unless @collective.allows_sending_by? @box_user
80
- flash[:error] = :access_to_that_box_denied.l
81
- redirect_to message_train.collective_box_url(
82
- @collective.path_part,
83
- :in
84
- )
85
- end
86
- end
87
- end
60
+ def get_collective_model(table)
61
+ MessageTrain.configuration.recipient_tables[table.to_sym].constantize
88
62
  end
89
63
 
90
64
  def load_box
@@ -100,39 +74,37 @@ module MessageTrainSupport
100
74
  end
101
75
 
102
76
  def load_objects
103
- @objects = {}
104
- @objects['conversations'] = {}
105
- @objects['messages'] = {}
106
- if params[:objects].present?
107
- params[:objects].each do |type, list|
108
- list.each do |key, list_item|
109
- @objects[type][key.to_s] = list_item.to_i
110
- end
77
+ @objects = { 'conversations' => {}, 'messages' => {} }
78
+ return unless params[:objects].present?
79
+ params[:objects].each do |type, list|
80
+ list.each do |key, list_item|
81
+ @objects[type][key.to_s] = list_item.to_i
111
82
  end
112
83
  end
113
84
  end
114
85
 
115
86
  def respond_to_marking
116
- if !@box.errors.all.empty?
117
- respond_to do |format|
118
- format.html do
119
- flash[:error] = @box.message
120
- show
121
- end
122
- format.json { render :results, status: :unprocessable_entity }
87
+ @box.errors.any? ? marking_error : marking_success
88
+ end
89
+
90
+ def marking_error
91
+ respond_to do |format|
92
+ format.html do
93
+ flash[:error] = @box.message
94
+ show
123
95
  end
124
- else
125
- respond_to do |format|
126
- format.html do
127
- if @box.results.all.empty?
128
- flash[:alert] = @box.message
129
- else
130
- flash[:notice] = @box.message
131
- end
132
- show
133
- end
134
- format.json { render :results, status: :accepted }
96
+ format.json { render :results, status: :unprocessable_entity }
97
+ end
98
+ end
99
+
100
+ def marking_success
101
+ respond_to do |format|
102
+ format.html do
103
+ flash_type = @box.results.any? ? :notice : :alert
104
+ flash[flash_type] = @box.message
105
+ show
135
106
  end
107
+ format.json { render :results, status: :accepted }
136
108
  end
137
109
  end
138
110
  end
@@ -2,5 +2,6 @@ module MessageTrain
2
2
  # Application controller
3
3
  class ApplicationController < ::ApplicationController
4
4
  include MessageTrainSupport
5
+ include MessageTrainAuthorization
5
6
  end
6
7
  end
@@ -1,11 +1,12 @@
1
1
  module MessageTrain
2
2
  # Boxes controller
3
3
  class BoxesController < MessageTrain::ApplicationController
4
- before_filter :load_conversations
4
+ before_action :load_conversations
5
5
 
6
6
  # GET /box/:division
7
7
  def show
8
- @conversations = @conversations.page(params[:page])
8
+ @conversations = @conversations.order(updated_at: :desc)
9
+ .page(params[:page])
9
10
  render :show
10
11
  end
11
12
 
@@ -19,8 +20,8 @@ module MessageTrain
19
20
 
20
21
  # DELETE /box/:division
21
22
  def destroy
22
- if %w( ignore unignore ).include? params[:mark_to_set]
23
- @box.send(params[:mark_to_set], @objects)
23
+ if %w(ignore unignore).include? params[:mark_to_set]
24
+ MessageTrain::Ignore.send(params[:mark_to_set], @objects, @box)
24
25
  end
25
26
  respond_to_marking
26
27
  end
@@ -1,12 +1,14 @@
1
1
  module MessageTrain
2
2
  # Conversations controller
3
3
  class ConversationsController < MessageTrain::ApplicationController
4
- before_filter :load_conversation
5
- after_filter :mark_as_read
4
+ before_action :load_conversation
5
+ after_action :mark_as_read
6
6
 
7
7
  # GET /box/:division/conversations/:id
8
8
  def show
9
- @messages = @conversation.messages.page(params[:page])
9
+ @messages = @conversation.messages
10
+ .order(updated_at: :desc)
11
+ .page(params[:page])
10
12
  render :show
11
13
  @box.mark :read, @messages
12
14
  end
@@ -21,8 +23,8 @@ module MessageTrain
21
23
 
22
24
  # DELETE /box/:division/conversations/:id
23
25
  def destroy
24
- if %w( ignore unignore ).include? params[:mark_to_set]
25
- @box.send(params[:mark_to_set], @conversation)
26
+ if %w(ignore unignore).include? params[:mark_to_set]
27
+ MessageTrain::Ignore.send(params[:mark_to_set], @conversation, @box)
26
28
  end
27
29
  respond_to_marking
28
30
  end
@@ -1,7 +1,7 @@
1
1
  module MessageTrain
2
2
  # Messages controller
3
3
  class MessagesController < MessageTrain::ApplicationController
4
- before_filter :load_message, only: [:show, :edit, :update]
4
+ before_action :load_message, only: [:show, :edit, :update]
5
5
 
6
6
  # GET /box/in/messages/1
7
7
  def show
@@ -12,9 +12,12 @@ module MessageTrain
12
12
 
13
13
  # GET /box/:division/messages/new
14
14
  def new
15
- @message = @box.new_message(
16
- message_train_conversation_id: params[:conversation_id]
17
- )
15
+ if params[:conversation_id]
16
+ @conversation = @box.find_conversation params[:conversation_id]
17
+ @message = @conversation.new_reply(box: @box)
18
+ else
19
+ @message = MessageTrain::Message.new(box: @box)
20
+ end
18
21
  end
19
22
 
20
23
  # GET /box/:division/messages/:id/edit
@@ -25,42 +28,55 @@ module MessageTrain
25
28
  # POST /box/:division/messages
26
29
  def create
27
30
  @message = @box.send_message(message_params)
28
- if @box.errors.all.empty?
29
- if @message.draft
30
- redirect_to message_train.box_path(:drafts), alert: @box.message
31
- else
32
- redirect_to message_train.box_path(:sent), notice: @box.message
33
- end
31
+ return create_error if @box.errors.any?
32
+ if @message.draft
33
+ redirect_to message_train.box_path(:drafts), alert: @box.message
34
34
  else
35
- flash[:error] = @box.message
36
- render :new
35
+ redirect_to message_train.box_path(:sent), notice: @box.message
37
36
  end
38
37
  end
39
38
 
40
39
  # PATCH/PUT /box/:division/messages/:id
41
40
  def update
42
- !@message.draft && raise(ActiveRecord::RecordNotFound)
43
41
  @box.update_message(@message, message_params)
44
- if @box.errors.all.empty?
45
- if @message.draft
46
- redirect_to(
47
- message_train.box_conversation_url(@box, @message.conversation),
48
- alert: @box.message
49
- )
50
- else
51
- redirect_to(
52
- message_train.box_path(:sent),
53
- notice: @box.message
54
- )
55
- end
42
+
43
+ return update_error if @box.errors.any?
44
+
45
+ if @message.draft
46
+ redirect_draft
56
47
  else
57
- flash[:error] = @box.message
58
- render :edit
48
+ redirect_ready
59
49
  end
60
50
  end
61
51
 
62
52
  private
63
53
 
54
+ def redirect_draft
55
+ redirect_to(
56
+ message_train.box_conversation_url(@box, @message.conversation),
57
+ alert: @box.message
58
+ )
59
+ end
60
+
61
+ def redirect_ready
62
+ redirect_to(
63
+ message_train.box_path(:sent),
64
+ notice: @box.message
65
+ )
66
+ end
67
+
68
+ def update_error
69
+ flash[:error] = @box.message
70
+ render :edit
71
+ false
72
+ end
73
+
74
+ def create_error
75
+ flash[:error] = @box.message
76
+ render :new
77
+ false
78
+ end
79
+
64
80
  def load_message
65
81
  @message = @box.find_message(params[:id])
66
82
  end
@@ -1,17 +1,18 @@
1
1
  module MessageTrain
2
2
  # Participants controller
3
3
  class ParticipantsController < MessageTrain::ApplicationController
4
- before_filter :load_participants
5
- before_filter :load_participant, only: :show
4
+ before_action :load_model
5
+ before_action :load_participants
6
+ before_action :load_participant, only: :show
6
7
 
7
- # GET /box/:division/participants/:model
8
+ # GET /box/:division/participants/:model.json
8
9
  def index
9
10
  respond_to do |format|
10
11
  format.json { render :index }
11
12
  end
12
13
  end
13
14
 
14
- # GET /box/:division/participants/:model/:id
15
+ # GET /box/:division/participants/:model/:id.json
15
16
  def show
16
17
  respond_to do |format|
17
18
  format.json { render :show }
@@ -20,29 +21,17 @@ module MessageTrain
20
21
 
21
22
  private
22
23
 
23
- def load_participants
24
+ def load_model
24
25
  params[:model].empty? && raise(ActiveRecord::RecordNotFound)
25
- model_sym = params[:model].to_sym
26
- model = MessageTrain.configuration.recipient_tables[model_sym].constantize
27
- method = MessageTrain.configuration.address_book_methods[model_sym]
28
- fallback_method = MessageTrain.configuration.address_book_method
26
+ @model = MessageTrain.configuration
27
+ .recipient_tables[params[:model].to_sym]
28
+ .constantize
29
+ end
30
+
31
+ def load_participants
29
32
  current_participant = send(MessageTrain.configuration.current_user_method)
30
- if !method.nil? && model.respond_to?(method)
31
- @participants = model.send(method, current_participant)
32
- elsif !fallback_method.nil? && model.respond_to?(fallback_method)
33
- @participants = model.send(fallback_method, current_participant)
34
- else
35
- @participants = model.all
36
- end
37
- if params[:query].present?
38
- field_name = MessageTrain.configuration.slug_columns[model_sym]
39
- pattern = Regexp.union('\\', '%', '_')
40
- query = params[:query].gsub(pattern) { |x| ['\\', x].join }
41
- @participants = @participants.where(
42
- "#{field_name} LIKE ?",
43
- "#{query}%"
44
- )
45
- end
33
+ @participants = @model.message_train_address_book(current_participant)
34
+ @participants = @participants.where_slug_starts_with(params[:query])
46
35
  end
47
36
 
48
37
  def load_participant