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
@@ -7,61 +7,90 @@ module MessageTrain
7
7
  has_many :attachments, through: :messages
8
8
 
9
9
  # Scopes
10
- default_scope { order(updated_at: :desc) }
10
+ scope :by_ignored, ->(p, flag) { flag ? ignored(p) : unignored(p) }
11
+
11
12
  scope :ignored, ->(participant) { where(id: ignored_ids_for(participant)) }
13
+
12
14
  scope :unignored, (lambda do |participant|
13
15
  where.not(id: ignored_ids_for(participant))
14
16
  end)
17
+
15
18
  scope :with_drafts_by, (lambda do |participant|
16
- joins(:messages).where(
17
- message_train_messages: {
18
- id: messages.drafts.with_receipts_by(participant)
19
- }
20
- )
19
+ messages.drafts.with_receipts_by(participant).conversations
21
20
  end)
21
+
22
22
  scope :with_ready_for, (lambda do |participant|
23
- joins(:messages).where(
24
- message_train_messages: {
25
- id: messages.ready.with_receipts_for(participant)
26
- }
27
- )
23
+ messages.ready.with_receipts_for(participant).conversations
28
24
  end)
25
+
29
26
  scope :with_messages_for, (lambda do |participant|
30
- joins(:messages).where(
31
- message_train_messages: {
32
- id: messages.with_receipts_for(participant)
33
- }
34
- )
27
+ messages.with_receipts_for(participant).conversations
28
+ end)
29
+
30
+ scope :without_trashed_for, (lambda do |participant|
31
+ where.not(id: messages.with_trashed_for(participant).conversations)
35
32
  end)
33
+
34
+ scope :without_deleted_for, (lambda do |participant|
35
+ where.not(id: messages.with_deleted_for(participant).conversations)
36
+ end)
37
+
36
38
  scope :with_messages_through, (lambda do |participant|
37
- joins(:messages).where(
38
- message_train_messages: {
39
- id: messages.with_receipts_through(participant)
40
- }
41
- )
39
+ messages.with_receipts_through(participant).conversations
42
40
  end)
43
41
 
44
42
  scope :filter_by_receipt_method, (lambda do |receipt_method, participant|
45
- where(
46
- id: where(nil).messages.receipts.send(receipt_method, participant)
47
- .conversation_ids
48
- )
43
+ messages.receipts.send(receipt_method, participant).conversations
44
+ end)
45
+
46
+ scope :filter_by_division, (lambda do |division|
47
+ found = if division == :drafts
48
+ with_drafts_by(participant)
49
+ else
50
+ with_ready_for(participant)
51
+ end
52
+ found.by_ignored(participant, division == :ignored)
49
53
  end)
50
54
 
51
- scope :ignored_ids_for, (lambda do |participant|
55
+ scope :filter_by_preposition, (lambda do |prep, *args|
56
+ messages.filter_by_receipt_method(prep, *args).conversations
57
+ end)
58
+
59
+ scope :filter_by_status_and_preposition, (lambda do |status, prep, *args|
60
+ case status
61
+ when :ready, :drafts
62
+ messages.send(status)
63
+ .filter_by_receipt_method(prep, *args)
64
+ .conversations
65
+ when :messages
66
+ filter_by_preposition(prep, *args)
67
+ else
68
+ filter_by_receipt_method("#{status}_#{prep}", *args)
69
+ end
70
+ end)
71
+
72
+ def self.ignored_ids_for(participant)
52
73
  MessageTrain::Ignore.find_all_by_participant(participant)
53
74
  .pluck(:message_train_conversation_id)
54
- end)
75
+ end
76
+
77
+ def self.messages
78
+ MessageTrain::Message.for_conversations(ids)
79
+ end
55
80
 
56
81
  def default_recipients_for(sender)
57
- default_recipients = []
58
- messages.with_receipts_for(sender).each do |conversation|
59
- conversation.receipts.each do |receipt|
60
- default_recipients << receipt.recipient
61
- end
62
- end
82
+ default_recipients = messages.with_receipts_for(sender).map do |c|
83
+ c.receipts.map(&:recipient)
84
+ end.flatten.uniq
63
85
  default_recipients.delete(sender)
64
- default_recipients.flatten.uniq
86
+ default_recipients
87
+ end
88
+
89
+ def new_reply(args)
90
+ args[:reply_recipients] = default_recipients_for(args.delete(:box).parent)
91
+ args[:subject] = "Re: #{subject}"
92
+ args[:body] = "<blockquote>#{messages.last.body}</blockquote><p></p>"
93
+ messages.build(args)
65
94
  end
66
95
 
67
96
  def participant_ignore(participant)
@@ -73,88 +102,56 @@ module MessageTrain
73
102
  end
74
103
 
75
104
  def participant_ignored?(participant)
76
- if ignores.empty?
77
- false
78
- else
79
- !ignores.find_all_by_participant(participant).empty?
80
- end
105
+ ignores.empty? ? false : ignores.find_all_by_participant(participant).any?
81
106
  end
82
107
 
83
108
  def mark(mark, participant)
84
109
  messages.mark(mark, participant)
85
110
  end
86
111
 
87
- def self.messages
88
- MessageTrain::Message.joins(:conversation).where(conversation: where(nil))
89
- end
90
-
91
- def method_missing(method_sym, *arguments, &block)
92
- # the first argument is a Symbol, so you need to_s it if you want to
93
- # pattern match
94
- if method_sym.to_s =~ /^includes_((.*)_(by|to|for|through))\?$/
95
- case Regexp.last_match[2]
96
- when 'ready', 'drafts'
97
- if Regexp.last_match[3] == 'by'
98
- messages.send(Regexp.last_match[2]).by(arguments.first).any?
99
- else
100
- messages.send(Regexp.last_match[2]).receipts.send(
101
- "receipts_#{Regexp.last_match[3]}".to_sym,
102
- arguments.first
103
- ).any?
104
- end
105
- else
106
- receipts.send(Regexp.last_match[1].to_sym, arguments.first).any?
107
- end
108
- else
109
- super
110
- end
112
+ def method_missing(method_sym, *args, &block)
113
+ string = method_sym.to_s
114
+ return super unless string =~ /\Aincludes_(.*)_(by|to|for|through)\?\z/
115
+ includes_matches_with_preposition?(
116
+ Regexp.last_match[1].to_sym, Regexp.last_match[2].to_sym, *args
117
+ )
111
118
  end
112
119
 
113
- def self.method_missing(method_sym, *arguments, &block)
114
- # the first argument is a Symbol, so you need to_s it if you want to
115
- # pattern match
116
- if method_sym.to_s =~ /^with_((.*)_(by|to|for|through))$/
117
- case Regexp.last_match[2]
118
- when 'ready', 'drafts'
119
- messages.send(
120
- Regexp.last_match[2]
121
- ).filter_by_receipt_method(
122
- "receipts_#{Regexp.last_match[3]}".to_sym,
123
- arguments.first
124
- ).conversations
125
- when 'messages'
126
- messages.filter_by_receipt_method(
127
- "receipts_#{Regexp.last_match[3]}".to_sym,
128
- arguments.first
129
- ).conversations
130
- else
131
- filter_by_receipt_method(
132
- Regexp.last_match[1].to_sym,
133
- arguments.first
134
- )
135
- end
136
- else
137
- super
120
+ def includes_matches_with_preposition?(flag, prep, *args)
121
+ unless [:ready, :drafts].include? flag
122
+ return includes_matching_receipts?("#{flag}_#{prep}".to_sym, *args)
138
123
  end
124
+ return includes_matching_messages_by?(flag, *args) if prep == 'by'
125
+ includes_matching_messages_with_prep?(flag, prep, *args)
139
126
  end
140
127
 
141
- # It's important to know Object defines respond_to to take two parameters:
142
- # the method to check, and whether to include private methods
143
- # http://www.ruby-doc.org/core/classes/Object.html#M000333
144
- def respond_to?(method_sym, include_private = false)
145
- if method_sym.to_s =~ /^includes_((.*)_(by|to|for|through))\?$/
146
- true
147
- else
148
- super
149
- end
128
+ def includes_matching_receipts?(match_method_sym, *args)
129
+ receipts.send(match_method_sym, *args).any?
150
130
  end
151
131
 
152
- def self.respond_to?(method_sym, include_private = false)
153
- if method_sym.to_s =~ /^with_(.*)_(by|to|for|through)$/
154
- true
155
- else
156
- super
157
- end
132
+ def respond_to_missing?(method_sym, include_private = false)
133
+ method_sym.to_s =~ /\Aincludes_.*_(by|to|for|through)\?\z/ || super
134
+ end
135
+
136
+ def self.method_missing(method_sym, *args, &block)
137
+ return super unless method_sym.to_s =~ /^with_(.*)_(by|to|for|through)$/
138
+ status = Regexp.last_match[1].to_sym
139
+ preposition = Regexp.last_match[2].to_sym
140
+ filter_by_status_and_preposition(status, preposition, *args)
141
+ end
142
+
143
+ def self.respond_to_missing?(method_sym, include_private = false)
144
+ method_sym.to_s =~ /^with_(.*)_(by|to|for|through)$/ || super
145
+ end
146
+
147
+ protected
148
+
149
+ def includes_matching_messages_by?(flag, *args)
150
+ messages.send(flag).by(*args).any?
151
+ end
152
+
153
+ def includes_matching_messages_with_prep?(flag, preposition, *args)
154
+ messages.send(flag).receipts.flagged(preposition, *args).any?
158
155
  end
159
156
  end
160
157
  end
@@ -1,6 +1,22 @@
1
1
  module MessageTrain
2
2
  # Ignore model
3
3
  class Ignore < ActiveRecord::Base
4
+ IGNORE_METHODS = {
5
+ 'Hash' => :ignore_hash,
6
+ 'Array' => :ignore_array,
7
+ 'String' => :ignore_id,
8
+ 'Fixnum' => :ignore_id,
9
+ 'MessageTrain::Conversation' => :ignore_conversation
10
+ }.freeze
11
+
12
+ UNIGNORE_METHODS = {
13
+ 'Hash' => :unignore_hash,
14
+ 'Array' => :unignore_array,
15
+ 'String' => :unignore_id,
16
+ 'Fixnum' => :unignore_id,
17
+ 'MessageTrain::Conversation' => :unignore_conversation
18
+ }.freeze
19
+
4
20
  belongs_to :participant, polymorphic: true
5
21
  belongs_to(
6
22
  :conversation,
@@ -14,11 +30,74 @@ module MessageTrain
14
30
  where(participant: participant)
15
31
  end)
16
32
 
17
- def self.conversations
33
+ scope :conversations, (lambda do
18
34
  MessageTrain::Conversation.joins(:ignores)
19
- .where(
20
- message_train_ignores: { id: where(nil) }
21
- )
35
+ .where(message_train_ignores: { id: where(nil) })
36
+ end)
37
+
38
+ def self.ignore(object, box)
39
+ method = IGNORE_METHODS[object.class.name]
40
+ return ignoring_error(object, box) if method.nil?
41
+ send(method, object, box)
42
+ end
43
+
44
+ def self.unignore(object, box)
45
+ method = UNIGNORE_METHODS[object.class.name]
46
+ return unignoring_error(object, box) if method.nil?
47
+ send(method, object, box)
48
+ end
49
+
50
+ def self.ignore_hash(object, box)
51
+ ignore object.values, box
52
+ end
53
+
54
+ def self.ignore_array(object, box)
55
+ object.collect { |item| ignore(item, box) }.uniq == [true]
56
+ end
57
+
58
+ def self.ignore_id(object, box)
59
+ ignore(box.find_conversation(object.to_i), box)
60
+ end
61
+
62
+ def self.ignore_conversation(object, box)
63
+ if box.authorize(object)
64
+ object.participant_ignore(box.participant)
65
+ box.results.add(object, :update_successful.l)
66
+ else
67
+ false
68
+ end
69
+ end
70
+
71
+ def self.ignoring_error(object, box)
72
+ box.errors.add(self, :cannot_ignore_type.l(type: object.class.name))
73
+ object
74
+ end
75
+
76
+ def self.unignore_hash(object, box)
77
+ unignore object.values, box
78
+ end
79
+
80
+ def self.unignore_array(object, box)
81
+ object.collect { |item| unignore(item, box) }.uniq == [true]
82
+ end
83
+
84
+ def self.unignore_id(object, box)
85
+ unignore(box.find_conversation(object.to_i), box)
86
+ end
87
+
88
+ def self.unignore_conversation(object, box)
89
+ if box.authorize(object)
90
+ object.participant_unignore(box.participant)
91
+ box.results.add(object, :update_successful.l)
92
+ object
93
+ else
94
+ false
95
+ end
96
+ end
97
+
98
+ def self.unignoring_error(object, box)
99
+ box.errors.add(self, :cannot_unignore_type.l(type: object.class.name))
100
+ object
22
101
  end
23
102
  end
24
103
  end
@@ -4,15 +4,20 @@ module MessageTrain
4
4
  # Serializations
5
5
  serialize :recipients_to_save, Hash
6
6
 
7
+ attr_accessor :box
8
+
7
9
  # Relationships
8
10
  belongs_to(
9
11
  :conversation,
10
12
  foreign_key: :message_train_conversation_id,
13
+ class_name: 'MessageTrain::Conversation',
11
14
  touch: true
12
15
  )
13
16
  belongs_to :sender, polymorphic: true
14
17
  has_many :attachments, foreign_key: :message_train_message_id
15
18
  has_many :receipts, foreign_key: :message_train_message_id
19
+ delegate :participant_ignored?, to: :conversation
20
+ delegate :send_receipts, to: :receipts
16
21
 
17
22
  # Validations
18
23
  validates_presence_of :sender, :subject
@@ -25,172 +30,116 @@ module MessageTrain
25
30
 
26
31
  # Nested Attributes
27
32
  accepts_nested_attributes_for(
28
- :attachments,
29
- reject_if: :all_blank,
30
- allow_destroy: true
33
+ :attachments, reject_if: :all_blank, allow_destroy: true
31
34
  )
32
35
 
33
36
  # Scopes
34
- default_scope { order(updated_at: :desc) }
35
37
  scope :ready, -> { where(draft: false) }
36
38
  scope :drafts, -> { where(draft: true) }
37
39
  scope :by, ->(participant) { where(sender: participant) }
38
40
  scope :drafts_by, ->(participant) { drafts.by(participant) }
39
41
  scope :filter_by_receipt_method, (lambda do |receipt_method, participant|
40
- where(
41
- id: where(nil).receipts.send(receipt_method, participant).message_ids
42
- )
42
+ receipts.send(receipt_method, participant).messages
43
43
  end)
44
+ scope :for_conversations, ->(c) { where conversation: c }
44
45
 
45
- def mark(mark_to_set, participant)
46
- receipt_to_mark = receipts.for(participant).first
47
- receipt_to_mark.present? && receipt_to_mark.mark(mark_to_set)
46
+ def self.conversation_ids
47
+ pluck(:message_train_conversation_id)
48
48
  end
49
49
 
50
- def self.mark(mark_to_set, participant)
51
- find_each do |message|
52
- message.mark(mark_to_set, participant)
53
- end
50
+ def self.conversations
51
+ MessageTrain::Conversation.where(id: conversation_ids)
54
52
  end
55
53
 
56
- def recipients
57
- recips = []
58
- receipts.recipient_receipt.each do |message|
59
- recips << message.received_through
60
- end
61
- recips.uniq
54
+ def self.receipts
55
+ MessageTrain::Receipt.for_messages(ids)
62
56
  end
63
57
 
64
- def self.conversation_ids
65
- pluck(:message_train_conversation_id)
58
+ def mark(mark_to_set, participant)
59
+ receipts.for(participant).mark(mark_to_set)
66
60
  end
67
61
 
68
- def self.receipts
69
- MessageTrain::Receipt.joins(:message)
70
- .where(message_train_messages: { id: where(nil) })
62
+ def self.mark(mark_to_set, participant)
63
+ find_each { |message| message.mark(mark_to_set, participant) }
71
64
  end
72
65
 
73
- def self.conversations
74
- MessageTrain::Conversation.joins(:messages)
75
- .where(
76
- message_train_messages: { id: where(nil) }
77
- )
66
+ def recipients
67
+ receipts.recipient_receipt.map(&:received_through).uniq
78
68
  end
79
69
 
80
- def method_missing(method_sym, *arguments, &block)
81
- # the first argument is a Symbol, so you need to_s it if you want to
82
- # pattern match
83
- if method_sym.to_s =~ /^is_((.*)_(by|to|for|through))\?$/
84
- !receipts.send(Regexp.last_match[1].to_sym, arguments.first).empty?
85
- elsif method_sym.to_s =~ /^mark_(.*)_for$/
86
- receipts.for(arguments.first).first.mark(Regexp.last_match[1].to_sym)
87
- else
88
- super
70
+ def reply_recipients=(recipients)
71
+ recipient_arrays = {}
72
+ recipients.each do |recipient|
73
+ table_name = recipient.class.table_name
74
+ recipient_arrays[table_name] ||= []
75
+ recipient_arrays[table_name] << recipient.message_train_slug
76
+ end
77
+ recipient_arrays.each do |key, array|
78
+ recipients_to_save[key] = array.join(', ')
89
79
  end
90
80
  end
91
81
 
92
- def self.method_missing(method_sym, *arguments, &block)
93
- # the first argument is a Symbol, so you need to_s it if you want to
94
- # pattern match
95
- if method_sym.to_s =~ /^with_(.*_(by|to|for|through))$/
96
- filter_by_receipt_method(Regexp.last_match[1].to_sym, arguments.first)
97
- else
98
- super
82
+ def method_missing(method_sym, *args, &block)
83
+ if method_sym.to_s =~ /^is_((.*)_(by|to|for|through))\?$/
84
+ return receipts.flagged(Regexp.last_match[1], *args).any?
85
+ end
86
+ if method_sym.to_s =~ /^mark_(.*)_for$/
87
+ return mark(Regexp.last_match[1], *args)
99
88
  end
89
+ super
100
90
  end
101
91
 
102
- # It's important to know Object defines respond_to to take two parameters:
103
- # the method to check, and whether to include private methods
104
- # http://www.ruby-doc.org/core/classes/Object.html#M000333
105
- def respond_to?(method_sym, include_private = false)
106
- if method_sym.to_s =~ /^is_.*_(by|to|for|through)\?$/ ||
107
- method_sym.to_s =~ /^mark_.*_for\?$/
108
- true
109
- else
110
- super
111
- end
92
+ def self.method_missing(method_sym, *args, &block)
93
+ return super unless method_sym.to_s =~ /^with_(.*_(by|to|for|through))$/
94
+ filter_by_receipt_method(Regexp.last_match[1].to_sym, args.first)
112
95
  end
113
96
 
114
- def self.respond_to?(method_sym, include_private = false)
115
- if method_sym.to_s =~ /^.*_(by|to|for|through)$/
116
- true
117
- else
118
- super
119
- end
97
+ def respond_to_missing?(method_sym, inc_private = false)
98
+ return true if method_sym.to_s =~ /^is_.*_(by|to|for|through)\?$/ ||
99
+ method_sym.to_s =~ /^mark_.*_for\?$/
100
+ super
101
+ end
102
+
103
+ def self.respond_to_missing?(method_sym, inc_private = false)
104
+ method_sym.to_s =~ /^.*_(by|to|for|through)$/ ? true : super
120
105
  end
121
106
 
122
107
  private
123
108
 
124
109
  def create_conversation_if_blank
125
- if conversation.nil?
126
- self.conversation = Conversation.create(subject: subject)
127
- end
110
+ return if conversation.present?
111
+ self.conversation = Conversation.create(subject: subject)
128
112
  end
129
113
 
130
114
  def generate_sender_receipt
131
- receipts.first_or_create!(
132
- recipient: sender,
133
- received_through: sender,
134
- sender: true
135
- )
115
+ receipts.generate_for_sender(sender)
136
116
  end
137
117
 
138
118
  def generate_receipts_or_set_draft
139
- unless draft
140
- recipients_to_save.each do |table, slugs|
141
- slugs = slugs.split(',')
142
- sender.class.table_name == table && (slugs -= [sender.slug])
143
- slugs.each do |slug|
144
- send_receipts(table, slug)
145
- end
146
- end
147
- reload
148
- if recipients.empty?
149
- update_attribute :draft, true
150
- else
151
- conversation.update_attribute(:updated_at, Time.now)
152
- end
153
- end
119
+ return if draft
120
+ recipients_to_save.each { |table, slugs| save_recipients(table, slugs) }
121
+ recipients.empty? ? update_attribute(:draft, true) : conversation.touch
122
+ end
123
+
124
+ def save_recipients(table, slugs)
125
+ slugs = slugs.split(',')
126
+ slugs -= [sender.slug] if sender.class.table_name == table
127
+ slugs.each { |slug| send_receipts(table, slug) }
154
128
  end
155
129
 
156
130
  def set_conversation_subject_if_alone
157
- if conversation.messages.count == 1
158
- conversation.update_attribute(:subject, subject)
159
- end
131
+ return if conversation.messages.count != 1
132
+ conversation.update_attribute(:subject, subject)
160
133
  end
161
134
 
162
135
  def send_receipts(table, slug)
163
- model_name = table.classify
164
- model = model_name.constantize
165
- slug = slug.strip
166
- slug_column = MessageTrain.configuration
167
- .slug_columns[table.to_sym] || :slug
168
- if model.exists?(slug_column => slug)
169
- recipient = model.find_by(slug_column => slug)
170
- end_recipient_method = MessageTrain.configuration
171
- .valid_recipients_methods[
172
- table.to_sym
173
- ]
174
- if end_recipient_method.nil?
175
- unless conversation.participant_ignored?(recipient)
176
- receipts.create!(
177
- recipient: recipient,
178
- received_through: recipient
179
- )
180
- end
181
- else
182
- recipient.send(end_recipient_method).uniq.each do |end_recipient|
183
- next if conversation.participant_ignored?(end_recipient) ||
184
- end_recipient == sender
185
- receipts.create!(
186
- recipient: end_recipient,
187
- received_through: recipient
188
- )
189
- end
190
- end
191
- else
136
+ model = table.classify.constantize
137
+ recipient = model.find_by_message_train_slug(slug)
138
+ unless recipient.present?
192
139
  errors.add :recipients_to_save, :name_not_found.l(name: slug)
140
+ return
193
141
  end
142
+ receipts.send_to_or_through(recipient)
194
143
  end
195
144
  end
196
145
  end