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
@@ -3,29 +3,66 @@ module MessageTrain
3
3
  class Receipt < ActiveRecord::Base
4
4
  belongs_to :recipient, polymorphic: true
5
5
  belongs_to :received_through, polymorphic: true
6
- belongs_to(
7
- :message,
8
- foreign_key: :message_train_message_id,
9
- touch: true
10
- )
6
+ belongs_to :message, foreign_key: :message_train_message_id, touch: true
7
+ delegate :conversation, to: :message
11
8
  validates_presence_of :recipient, :message
12
9
 
13
- default_scope { order(updated_at: :desc) }
10
+ after_create :notify
11
+
14
12
  scope :sender_receipt, -> { where(sender: true) }
15
13
  scope :recipient_receipt, -> { where(sender: false) }
14
+ scope :for, ->(recipient) { where(recipient: recipient) }
16
15
  scope :by, ->(sender) { sender_receipt.for(sender) }
17
- scope :for, (lambda do |recipient|
18
- where(recipient: recipient)
19
- end)
20
16
  scope :to, ->(recipient) { recipient_receipt.for(recipient) }
21
- scope :through, (lambda do |received_through|
22
- where(received_through: received_through)
23
- end)
17
+ scope :through, ->(recipient) { where(received_through: recipient) }
24
18
  scope :trashed, ->(setting = true) { where(marked_trash: setting) }
25
19
  scope :read, ->(setting = true) { where(marked_read: setting) }
26
20
  scope :deleted, ->(setting = true) { where(marked_deleted: setting) }
21
+ scope :for_messages, ->(messages) { where(message: messages) }
22
+ scope :flagged, ->(flag, *args) { send(flag.to_sym, *args) }
27
23
 
28
- after_create :notify
24
+ def self.message_ids
25
+ pluck(:message_train_message_id)
26
+ end
27
+
28
+ def self.messages
29
+ MessageTrain::Message.where(id: message_ids)
30
+ end
31
+
32
+ def self.conversation_ids
33
+ messages.conversation_ids
34
+ end
35
+
36
+ def self.conversations
37
+ MessageTrain::Conversation.where(id: conversation_ids)
38
+ end
39
+
40
+ def self.generate_for_sender(sender)
41
+ first_or_create!(recipient: sender, received_through: sender, sender: 1)
42
+ end
43
+
44
+ def self.send_to_or_through(recipient)
45
+ if recipient.class.collective?
46
+ send_through recipient, recipient.class.valid_recipients_method
47
+ else
48
+ send_to recipient
49
+ end
50
+ end
51
+
52
+ def self.send_to(recipient)
53
+ receipt = new recipient: recipient, received_through: recipient
54
+ return if receipt.conversation.participant_ignored?(recipient)
55
+ receipt.save
56
+ end
57
+
58
+ def self.send_through(recipient, end_recipient_method)
59
+ recipient.send(end_recipient_method).distinct.each do |end_recipient|
60
+ receipt = new recipient: end_recipient, received_through: recipient
61
+ next if receipt.conversation.participant_ignored?(end_recipient) ||
62
+ receipt.message.sender == end_recipient
63
+ receipt.save
64
+ end
65
+ end
29
66
 
30
67
  def mark(mark_to_set)
31
68
  if mark_to_set.to_s =~ /^un/
@@ -39,47 +76,35 @@ module MessageTrain
39
76
  update_attribute(column, setting)
40
77
  end
41
78
 
42
- def self.message_ids
43
- pluck(:message_train_message_id)
44
- end
45
-
46
- def self.messages
47
- MessageTrain::Message.joins(:receipts)
48
- .where(message_train_receipts: { id: where(nil) })
79
+ def self.mark(mark_to_set)
80
+ where(nil).each { |receipt| receipt.mark(mark_to_set) }
49
81
  end
50
82
 
51
- def self.conversation_ids
52
- messages.conversation_ids
83
+ def self.method_missing(method_sym, *args, &block)
84
+ method_string = method_sym.to_s
85
+ if method_string =~ /\A(.*)_(by|to|for|through)\z/
86
+ first_sym = Regexp.last_match[1].to_sym
87
+ second_sym = Regexp.last_match[2].to_sym
88
+ return run_prepositional_method(first_sym, second_sym, *args)
89
+ elsif method_string =~ /\Aun(.*)\z/
90
+ first_sym = Regexp.last_match[1].to_sym
91
+ return run_un_method(first_sym)
92
+ end
93
+ super
53
94
  end
54
95
 
55
- def self.conversations
56
- MessageTrain::Conversation.joins(:receipts)
57
- .where(
58
- message_train_receipts: { id: where(nil) }
59
- )
96
+ def self.run_prepositional_method(first_sym, second_sym, *args)
97
+ return send(second_sym, *args) if first_sym == :receipts
98
+ send(first_sym).send(second_sym, *args)
60
99
  end
61
100
 
62
- def self.method_missing(method_sym, *arguments, &block)
63
- # the first argument is a Symbol, so you need to_s it if you want to
64
- # pattern match
65
- if method_sym.to_s =~ /^receipts_(by|to|for|through)$/
66
- send(Regexp.last_match[1].to_sym, arguments.first)
67
- elsif method_sym.to_s =~ /^(.*)_(by|to|for|through)$/
68
- send(Regexp.last_match[1].to_sym)
69
- .send(Regexp.last_match[2].to_sym, arguments.first)
70
- elsif method_sym.to_s =~ /^un(.*)$/
71
- send(Regexp.last_match[1].to_sym, false)
72
- else
73
- super
74
- end
101
+ def self.run_un_method(first_sym)
102
+ send(first_sym, false)
75
103
  end
76
104
 
77
- # It's important to know Object defines respond_to to take two parameters:
78
- # the method to check, and whether to include private methods
79
- # http://www.ruby-doc.org/core/classes/Object.html#M000333
80
- def self.respond_to?(method_sym, include_private = false)
81
- if method_sym.to_s =~ /^(.*)_(by|to|for|through)$/ ||
82
- method_sym.to_s =~ /^un(.*)$/
105
+ def self.respond_to_missing?(method_sym, include_private = false)
106
+ if method_sym.to_s =~ /\A(.*)_(by|to|for|through)\z/ ||
107
+ method_sym.to_s =~ /\Aun(.*)\z/
83
108
  true
84
109
  else
85
110
  super
@@ -89,9 +114,8 @@ module MessageTrain
89
114
  private
90
115
 
91
116
  def notify
92
- unless sender? || recipient.unsubscribed_from?(received_through)
93
- ReceiptMailer.notification_email(self).deliver_later
94
- end
117
+ return if sender? || recipient.unsubscribed_from?(received_through)
118
+ ReceiptMailer.notification_email(self).deliver_now
95
119
  end
96
120
  end
97
121
  end
@@ -1,12 +1,16 @@
1
- - if @collective.nil?
2
- - add_title @box.title
3
- - marking_path = message_train.box_path(@box.division)
4
- - else
5
- - add_title collective_name(@collective) + ' ' + @box.title
6
- - marking_path = message_train.collective_box_path(@collective.path_part, @box.division)
1
+ :ruby
2
+ if @collective.nil?
3
+ add_title @box.title
4
+ marking_path = message_train.box_path(@box.division)
5
+ else
6
+ add_title collective_name(@collective) + ' ' + @box.title
7
+ marking_path = message_train.collective_box_path(@collective.path_part, @box.division)
8
+ end
7
9
  - cache ['message-train', 'boxes-show', @box_user, @box] do
8
10
  = form_tag marking_path, method: :put, remote: true, id: 'box', data: { type: :json } do
9
- - unless @conversations.empty?
11
+ - if @conversations.empty?
12
+ %em= :box_is_empty.l
13
+ - else
10
14
  #box-actions.box-actions
11
15
  .btn-group.check-all
12
16
  %button.btn.btn-default{ type: 'button' }
@@ -22,6 +22,7 @@ en:
22
22
  at_time_through_received_a_message: "At %{time}, %{through} received a message: <a href=\"%{path}\">%{subject}</a>"
23
23
  attachment_preview: 'Attachment Preview'
24
24
  attachments: 'Attachments'
25
+ box_is_empty: 'This box is empty.'
25
26
  box_title_in: 'Inbox'
26
27
  box_title_sent: 'Sent'
27
28
  box_title_all: 'All'
data/config/routes.rb CHANGED
@@ -30,26 +30,20 @@ MessageTrain::Engine.routes.draw do
30
30
  end
31
31
 
32
32
  match(
33
- '/box(/*path)' => redirect do |_p, req|
34
- req.flash[:error] = :you_must_sign_in_or_sign_up_to_continue.l
35
- MessageTrain.configuration.user_sign_in_path
36
- end,
33
+ '/box(/*path)',
34
+ to: 'boxes#redirect_to_sign_in',
37
35
  via: [:get, :put, :post, :delete]
38
36
  )
39
37
 
40
38
  match(
41
- '/collectives(/*path)' => redirect do |_p, req|
42
- req.flash[:error] = :you_must_sign_in_or_sign_up_to_continue.l
43
- MessageTrain.configuration.user_sign_in_path
44
- end,
39
+ '/collectives(/*path)',
40
+ to: 'boxes#redirect_to_sign_in',
45
41
  via: [:get, :put, :post, :delete]
46
42
  )
47
43
 
48
44
  match(
49
- '/unsubscribes(/*path)' => redirect do |_p, req|
50
- req.flash[:error] = :you_must_sign_in_or_sign_up_to_continue.l
51
- MessageTrain.configuration.user_sign_in_path
52
- end,
45
+ '/unsubscribes(/*path)',
46
+ to: 'unsubscribes#redirect_to_sign_in',
53
47
  via: [:get, :put, :post, :delete]
54
48
  )
55
49
  end
data/lib/message_train.rb CHANGED
@@ -13,9 +13,11 @@ module MessageTrain
13
13
  require 'message_train/localization'
14
14
  require 'message_train/version'
15
15
  require 'message_train/mixin'
16
+ require 'message_train/class_methods'
17
+ require 'message_train/instance_methods'
16
18
 
17
19
  require 'haml-rails'
18
20
  require 'bootstrap_leather'
19
21
  end
20
22
 
21
- ActiveRecord::Base.send(:include, MessageTrain::Mixin)
23
+ ActiveRecord::Base.send(:extend, MessageTrain::Mixin)
@@ -0,0 +1,51 @@
1
+ module MessageTrain
2
+ # Extended when message_train mixin is run
3
+ module ClassMethods
4
+ def message_train_address_book(for_participant)
5
+ method = MessageTrain.configuration.address_book_methods[
6
+ message_train_table_sym
7
+ ]
8
+ method ||= MessageTrain.configuration.address_book_method
9
+ if method.present? && respond_to?(method)
10
+ send(method, for_participant)
11
+ else
12
+ all
13
+ end
14
+ end
15
+
16
+ def find_by_message_train_slug(slug)
17
+ find_by(slug_column => slug.strip)
18
+ end
19
+
20
+ def where_slug_starts_with(string)
21
+ return where(nil) unless string.present?
22
+ pattern = Regexp.union('\\', '%', '_')
23
+ string = string.gsub(pattern) { |x| ['\\', x].join }
24
+ where("#{slug_column} LIKE ?", "#{string}%")
25
+ end
26
+
27
+ def slug_column
28
+ MessageTrain.configuration.slug_columns[message_train_table_sym] || :slug
29
+ end
30
+
31
+ def name_column
32
+ MessageTrain.configuration.name_columns[message_train_table_sym] || :name
33
+ end
34
+
35
+ def valid_senders_method
36
+ MessageTrain.configuration
37
+ .valid_senders_methods[message_train_table_sym] ||
38
+ :self_collection
39
+ end
40
+
41
+ def valid_recipients_method
42
+ MessageTrain.configuration
43
+ .valid_recipients_methods[message_train_table_sym] ||
44
+ :self_collection
45
+ end
46
+
47
+ def collective?
48
+ valid_senders_method != :self_collection
49
+ end
50
+ end
51
+ end
@@ -1,12 +1,34 @@
1
1
  # MessageTrain module
2
2
  module MessageTrain
3
+ # @conversions[:mixin_option] = :configuration_name
4
+ @conversions = {}
5
+ @conversions[:slug_column] = :slug_columns
6
+ @conversions[:name_column] = :name_columns
7
+ @conversions[:collectives_for_recipient] = :collectives_for_recipient_methods
8
+ @conversions[:valid_recipients] = :valid_recipients_methods
9
+ @conversions[:valid_senders] = :valid_senders_methods
10
+ @conversions[:address_book_method] = :address_book_methods
11
+
3
12
  def self.configure(configuration = MessageTrain::Configuration.new)
4
- block_given? && yield(configuration)
5
- @@configuration = configuration
13
+ yield(configuration) if block_given?
14
+ @configuration = configuration
6
15
  end
7
16
 
8
17
  def self.configuration
9
- @@configuration ||= MessageTrain::Configuration.new
18
+ @configuration ||= MessageTrain::Configuration.new
19
+ end
20
+
21
+ def self.configure_table(table_sym, name, options)
22
+ configure(@configuration) do |config|
23
+ config.recipient_tables[table_sym] = name
24
+ @conversions.each do |mixin_option_sym, configuration_name_sym|
25
+ value = options[mixin_option_sym]
26
+ next unless value.present?
27
+ setting = config.send(configuration_name_sym)
28
+ setting[table_sym] = value
29
+ config.send("#{configuration_name_sym}=", setting)
30
+ end
31
+ end
10
32
  end
11
33
 
12
34
  # MessageTrain configuration
@@ -26,6 +48,8 @@ module MessageTrain
26
48
  :from_email,
27
49
  :site_name
28
50
 
51
+ # rubocop:disable Metrics/MethodLength
52
+ # Don't see any way to shorten this
29
53
  def initialize
30
54
  self.recipient_tables = {}
31
55
  self.slug_columns = { users: :slug }
@@ -42,5 +66,6 @@ module MessageTrain
42
66
  self.from_email = ''
43
67
  self.site_name = 'Example Site Name'
44
68
  end
69
+ # rubocop:enable Metrics/MethodLength
45
70
  end
46
71
  end
@@ -0,0 +1,209 @@
1
+ module MessageTrain
2
+ # Included in method when message_train mixin is run
3
+ module InstanceMethods
4
+ def self.included(base)
5
+ base.send :include, InstanceMethods::GeneralMethods
6
+ base.message_train_relationships.include?(:recipient) &&
7
+ base.send(:include, InstanceMethods::RecipientMethods)
8
+ end
9
+
10
+ # Included by InstanceMethods when message_train mixin is run
11
+ module GeneralMethods
12
+ BOX_DEFINITIONS = {
13
+ in: :with_untrashed_to,
14
+ sent: :with_untrashed_by,
15
+ all: :with_untrashed_for,
16
+ drafts: :with_drafts_by,
17
+ trash: :with_trashed_for,
18
+ ignored: :ignored
19
+ }.freeze
20
+
21
+ BOX_OMISSION_DEFINITIONS = {
22
+ trash: :without_trashed_for,
23
+ drafts: :with_ready_for,
24
+ ignored: :unignored
25
+ }.freeze
26
+
27
+ def path_part
28
+ return unless self.class.collective?
29
+ # This must mean it's a collective
30
+ "#{self.class.table_name}:#{message_train_slug}"
31
+ end
32
+
33
+ def valid_senders
34
+ send(self.class.valid_senders_method)
35
+ end
36
+
37
+ def allows_sending_by?(sender)
38
+ valid_senders.include? sender
39
+ end
40
+
41
+ def valid_recipients
42
+ send(self.class.valid_recipients_method)
43
+ end
44
+
45
+ def allows_access_by?(recipient)
46
+ allows_receiving_by?(recipient) || allows_sending_by?(recipient)
47
+ end
48
+
49
+ def allows_receiving_by?(recipient)
50
+ return false if valid_recipients.empty?
51
+ valid_recipients.include? recipient
52
+ end
53
+
54
+ def self_collection
55
+ # This turns a single record into an active record collection.
56
+ self.class.where(id: id)
57
+ end
58
+
59
+ def conversations(*args)
60
+ division = args[0] || :in
61
+ participant = args[1] || self
62
+ definition_method = BOX_DEFINITIONS[division]
63
+ return if definition_method.nil?
64
+ conversations = defined_conversations(definition_method, participant)
65
+ BOX_OMISSION_DEFINITIONS.each do |division_key, omission_method|
66
+ next if division_key == division # Because not to be omitted
67
+ conversations = conversations.send(omission_method, participant)
68
+ end
69
+ conversations
70
+ end
71
+
72
+ def defined_conversations(definition, participant)
73
+ MessageTrain::Conversation.with_messages_through(self)
74
+ .without_deleted_for(participant)
75
+ .send(definition, participant)
76
+ end
77
+
78
+ def boxes_for_participant(participant)
79
+ original_order = [:in, :sent, :all, :drafts, :trash, :ignored]
80
+ divisions = [:all, :trash]
81
+ if respond_to?(:messages) || allows_sending_by?(participant)
82
+ divisions += [:sent, :drafts]
83
+ end
84
+ divisions += [:in, :ignored] if allows_receiving_by?(participant)
85
+ divisions.sort_by! { |x| original_order.index x }
86
+ divisions.collect { |d| MessageTrain::Box.new(self, d, participant) }
87
+ end
88
+
89
+ def all_conversations(*args)
90
+ participant = args[0] || self
91
+ results = MessageTrain::Conversation.with_messages_through(self)
92
+ return [] if results.empty?
93
+ results.with_messages_for(participant)
94
+ end
95
+
96
+ def all_messages(*args)
97
+ participant = args[0] || self
98
+ results = MessageTrain::Message.with_receipts_through(self)
99
+ return [] if results.empty?
100
+ results.with_receipts_for(participant)
101
+ end
102
+
103
+ def unsubscribed_from_all?
104
+ unsubscribes.where(from: nil).exists?
105
+ end
106
+
107
+ def unsubscribed_from?(from)
108
+ unsubscribed_from_all? || unsubscribes.where(from: from).exists?
109
+ end
110
+
111
+ def unsubscribe_from(from)
112
+ unsubscribes.find_or_create_by(from: from)
113
+ end
114
+
115
+ def subscriptions
116
+ subscriptions = [self_subscription]
117
+ subscriptions += collective_boxes.values.map do |boxes|
118
+ boxes.map { |box| subscription(box) }
119
+ end
120
+ subscriptions.flatten.compact
121
+ end
122
+ end
123
+
124
+ # Included by InstanceMethods when message_train mixin is run, if this is a
125
+ # recipient
126
+ module RecipientMethods
127
+ def box(*args)
128
+ division = args[0] || :in
129
+ participant = args[1] || self
130
+ @box ||= MessageTrain::Box.new(self, division, participant)
131
+ end
132
+
133
+ def collective_boxes(*args)
134
+ division = args[0] || :in
135
+ participant = args[1] || self
136
+ cb_tables = MessageTrain.configuration
137
+ .collectives_for_recipient_methods
138
+ return {} if cb_tables.empty?
139
+ Hash[cb_tables.map do |key, value|
140
+ box = table_collective_box(key, value, division, participant)
141
+ [key, box]
142
+ end]
143
+ end
144
+
145
+ def collective_boxes_unread_counts
146
+ Hash[collective_boxes.map do |key, collectives|
147
+ [key, collectives.collect(&:unread_count).sum]
148
+ end]
149
+ end
150
+
151
+ def collective_boxes_show_flags
152
+ Hash[collective_boxes.map do |key, collectives|
153
+ flag = collectives.select do |collective_box|
154
+ collective_box.parent.allows_access_by?(self)
155
+ end.any?
156
+ [key, flag]
157
+ end]
158
+ end
159
+
160
+ def table_collective_box(
161
+ table_sym, collectives_method, division, participant
162
+ )
163
+ model = MessageTrain.configuration
164
+ .recipient_tables[table_sym]
165
+ .constantize
166
+ collectives = model.send(collectives_method, participant)
167
+ collectives.map { |x| x.box(division, participant) }.compact
168
+ end
169
+
170
+ def all_boxes(*args)
171
+ participant = args[0] || self
172
+ divisions = [:in, :sent, :all, :drafts, :trash, :ignored]
173
+ divisions.collect do |division|
174
+ MessageTrain::Box.new(self, division, participant)
175
+ end
176
+ end
177
+
178
+ def message_train_name
179
+ send(self.class.name_column)
180
+ end
181
+
182
+ def message_train_slug
183
+ send(self.class.slug_column)
184
+ end
185
+
186
+ protected
187
+
188
+ def self_subscription
189
+ {
190
+ from: self, from_type: self.class.name, from_id: id,
191
+ from_name: :messages_directly_to_myself.l,
192
+ unsubscribe: unsubscribes.find_by(from: self)
193
+ }
194
+ end
195
+
196
+ def subscription(box)
197
+ parent = box.parent
198
+ return unless parent.allows_receiving_by?(self)
199
+ {
200
+ from: parent, from_type: parent.class.name, from_id: parent.id,
201
+ from_name: :messages_to_collective.l(
202
+ collective: parent.message_train_name
203
+ ),
204
+ unsubscribe: unsubscribes.find_by(from: parent)
205
+ }
206
+ end
207
+ end
208
+ end
209
+ end