message_train 0.6.17 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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