mailboxer 0.10.3 → 0.11.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/Appraisals +19 -0
- data/LICENSE.txt +1 -0
- data/README.md +45 -26
- data/Rakefile +4 -0
- data/app/mailers/message_mailer.rb +4 -4
- data/app/models/conversation.rb +114 -91
- data/app/models/mailbox.rb +16 -15
- data/app/models/message.rb +24 -22
- data/app/models/notification.rb +37 -24
- data/app/models/receipt.rb +37 -15
- data/gemfiles/rails3.0.gemfile +8 -0
- data/gemfiles/rails3.1.gemfile +8 -0
- data/gemfiles/rails3.2.gemfile +8 -0
- data/gemfiles/rails4.0.gemfile +8 -0
- data/lib/mailboxer.rb +13 -7
- data/lib/mailboxer/engine.rb +1 -2
- data/lib/mailboxer/models/messageable.rb +44 -22
- data/mailboxer.gemspec +9 -4
- data/spec/dummy/config/environments/test.rb +1 -3
- data/spec/mailers/message_mailer_spec.rb +69 -70
- data/spec/models/conversation_spec.rb +22 -0
- data/spec/models/mailbox_spec.rb +36 -0
- data/spec/models/mailboxer_models_messageable_spec.rb +8 -5
- data/spec/models/message_spec.rb +6 -0
- data/spec/models/receipt_spec.rb +13 -1
- metadata +25 -5
data/app/models/mailbox.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class Mailbox
|
2
2
|
attr_accessor :type
|
3
3
|
attr_reader :messageable
|
4
|
+
|
4
5
|
#Initializer method
|
5
6
|
def initialize(messageable)
|
6
7
|
@messageable = messageable
|
@@ -13,7 +14,8 @@ class Mailbox
|
|
13
14
|
if (options[:read].present? and options[:read]==false) or (options[:unread].present? and options[:unread]==true)
|
14
15
|
notifs = notifs.unread
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
notifs
|
17
19
|
end
|
18
20
|
|
19
21
|
#Returns the conversations for the messageable
|
@@ -39,6 +41,8 @@ class Mailbox
|
|
39
41
|
conv = Conversation.sentbox(@messageable)
|
40
42
|
when 'trash'
|
41
43
|
conv = Conversation.trash(@messageable)
|
44
|
+
when 'not_trash'
|
45
|
+
conv = Conversation.not_trash(@messageable)
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -46,7 +50,7 @@ class Mailbox
|
|
46
50
|
conv = conv.unread(@messageable)
|
47
51
|
end
|
48
52
|
|
49
|
-
|
53
|
+
conv
|
50
54
|
end
|
51
55
|
|
52
56
|
#Returns the conversations in the inbox of messageable
|
@@ -54,7 +58,7 @@ class Mailbox
|
|
54
58
|
#Same as conversations({:mailbox_type => 'inbox'})
|
55
59
|
def inbox(options={})
|
56
60
|
options = options.merge(:mailbox_type => 'inbox')
|
57
|
-
|
61
|
+
self.conversations(options)
|
58
62
|
end
|
59
63
|
|
60
64
|
#Returns the conversations in the sentbox of messageable
|
@@ -62,7 +66,7 @@ class Mailbox
|
|
62
66
|
#Same as conversations({:mailbox_type => 'sentbox'})
|
63
67
|
def sentbox(options={})
|
64
68
|
options = options.merge(:mailbox_type => 'sentbox')
|
65
|
-
|
69
|
+
self.conversations(options)
|
66
70
|
end
|
67
71
|
|
68
72
|
#Returns the conversations in the trash of messageable
|
@@ -70,33 +74,33 @@ class Mailbox
|
|
70
74
|
#Same as conversations({:mailbox_type => 'trash'})
|
71
75
|
def trash(options={})
|
72
76
|
options = options.merge(:mailbox_type => 'trash')
|
73
|
-
|
77
|
+
self.conversations(options)
|
74
78
|
end
|
75
79
|
|
76
80
|
#Returns all the receipts of messageable, from Messages and Notifications
|
77
81
|
def receipts(options = {})
|
78
|
-
|
82
|
+
Receipt.where(options).recipient(@messageable)
|
79
83
|
end
|
80
84
|
|
81
85
|
#Deletes all the messages in the trash of messageable. NOT IMPLEMENTED.
|
82
86
|
def empty_trash(options = {})
|
83
87
|
#TODO
|
84
|
-
|
88
|
+
false
|
85
89
|
end
|
86
90
|
|
87
91
|
#Returns if messageable is a participant of conversation
|
88
92
|
def has_conversation?(conversation)
|
89
|
-
|
93
|
+
conversation.is_participant?(@messageable)
|
90
94
|
end
|
91
95
|
|
92
96
|
#Returns true if messageable has at least one trashed message of the conversation
|
93
97
|
def is_trashed?(conversation)
|
94
|
-
|
98
|
+
conversation.is_trashed?(@messageable)
|
95
99
|
end
|
96
100
|
|
97
101
|
#Returns true if messageable has trashed all the messages of the conversation
|
98
102
|
def is_completely_trashed?(conversation)
|
99
|
-
|
103
|
+
conversation.is_completely_trashed?(@messageable)
|
100
104
|
end
|
101
105
|
|
102
106
|
#Returns the receipts of object for messageable as a ActiveRecord::Relation
|
@@ -110,12 +114,9 @@ class Mailbox
|
|
110
114
|
def receipts_for(object)
|
111
115
|
case object
|
112
116
|
when Message, Notification
|
113
|
-
|
117
|
+
object.receipt_for(@messageable)
|
114
118
|
when Conversation
|
115
|
-
|
116
|
-
else
|
117
|
-
return nil
|
119
|
+
object.receipts_for(@messageable)
|
118
120
|
end
|
119
121
|
end
|
120
|
-
|
121
122
|
end
|
data/app/models/message.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Message < Notification
|
2
|
-
attr_accessible :attachment
|
2
|
+
attr_accessible :attachment if Mailboxer.protected_attributes?
|
3
3
|
|
4
4
|
belongs_to :conversation, :validate => true, :autosave => true
|
5
5
|
validates_presence_of :sender
|
@@ -25,33 +25,25 @@ class Message < Notification
|
|
25
25
|
#Use Mailboxer::Models::Message.send_message instead.
|
26
26
|
def deliver(reply = false, should_clean = true)
|
27
27
|
self.clean if should_clean
|
28
|
-
|
28
|
+
|
29
29
|
#Receiver receipts
|
30
|
-
|
31
|
-
|
32
|
-
msg_receipt.notification = self
|
33
|
-
msg_receipt.is_read = false
|
34
|
-
msg_receipt.receiver = r
|
35
|
-
msg_receipt.mailbox_type = "inbox"
|
36
|
-
temp_receipts << msg_receipt
|
37
|
-
end
|
30
|
+
temp_receipts = recipients.map { |r| build_receipt(r, 'inbox') }
|
31
|
+
|
38
32
|
#Sender receipt
|
39
|
-
sender_receipt =
|
40
|
-
sender_receipt.notification = self
|
41
|
-
sender_receipt.is_read = true
|
42
|
-
sender_receipt.receiver = self.sender
|
43
|
-
sender_receipt.mailbox_type = "sentbox"
|
33
|
+
sender_receipt = build_receipt(sender, 'sentbox', true)
|
44
34
|
temp_receipts << sender_receipt
|
45
35
|
|
46
36
|
temp_receipts.each(&:valid?)
|
47
37
|
if temp_receipts.all? { |t| t.errors.empty? }
|
48
38
|
temp_receipts.each(&:save!) #Save receipts
|
49
|
-
self.recipients.each do |r|
|
50
39
|
#Should send an email?
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
40
|
+
if Mailboxer.uses_emails
|
41
|
+
if Mailboxer.mailer_wants_array
|
42
|
+
get_mailer.send_email(self, recipients).deliver
|
43
|
+
else
|
44
|
+
recipients.each do |recipient|
|
45
|
+
email_to = recipient.send(Mailboxer.email_method, self)
|
46
|
+
get_mailer.send_email(self, recipient).deliver if email_to.present?
|
55
47
|
end
|
56
48
|
end
|
57
49
|
end
|
@@ -59,8 +51,18 @@ class Message < Notification
|
|
59
51
|
self.conversation.touch
|
60
52
|
end
|
61
53
|
self.recipients=nil
|
62
|
-
|
54
|
+
self.on_deliver_callback.call(self) unless self.on_deliver_callback.nil?
|
55
|
+
end
|
56
|
+
sender_receipt
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def build_receipt(receiver, mailbox_type, is_read = false)
|
61
|
+
Receipt.new.tap do |receipt|
|
62
|
+
receipt.notification = self
|
63
|
+
receipt.is_read = is_read
|
64
|
+
receipt.receiver = receiver
|
65
|
+
receipt.mailbox_type = mailbox_type
|
63
66
|
end
|
64
|
-
return sender_receipt
|
65
67
|
end
|
66
68
|
end
|
data/app/models/notification.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
class Notification < ActiveRecord::Base
|
2
2
|
attr_accessor :recipients
|
3
|
-
attr_accessible :body, :subject, :global, :expires
|
3
|
+
attr_accessible :body, :subject, :global, :expires if Mailboxer.protected_attributes?
|
4
4
|
|
5
5
|
belongs_to :sender, :polymorphic => :true
|
6
6
|
belongs_to :notified_object, :polymorphic => :true
|
7
|
-
validates_presence_of :subject, :body
|
8
7
|
has_many :receipts, :dependent => :destroy
|
9
8
|
|
9
|
+
validates_presence_of :subject, :body
|
10
|
+
|
10
11
|
scope :recipient, lambda { |recipient|
|
11
|
-
joins(:receipts).where('receipts.receiver_id' => recipient.id,'receipts.receiver_type' => recipient.class.to_s)
|
12
|
+
joins(:receipts).where('receipts.receiver_id' => recipient.id,'receipts.receiver_type' => recipient.class.base_class.to_s)
|
12
13
|
}
|
13
14
|
scope :with_object, lambda { |obj|
|
14
15
|
where('notified_object_id' => obj.id,'notified_object_type' => obj.class.to_s)
|
@@ -35,7 +36,7 @@ class Notification < ActiveRecord::Base
|
|
35
36
|
notification.recipients = notification.recipients.uniq if recipients.respond_to?(:uniq)
|
36
37
|
notification.notified_object = obj if obj.present?
|
37
38
|
notification.notification_code = notification_code if notification_code.present?
|
38
|
-
|
39
|
+
notification.deliver sanitize_text, send_mail
|
39
40
|
end
|
40
41
|
|
41
42
|
#Takes a +Receipt+ or an +Array+ of them and returns +true+ if the delivery was
|
@@ -44,18 +45,18 @@ class Notification < ActiveRecord::Base
|
|
44
45
|
case receipts
|
45
46
|
when Receipt
|
46
47
|
receipts.valid?
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
receipts.errors.empty?
|
49
|
+
when Array
|
50
|
+
receipts.each(&:valid?)
|
51
|
+
receipts.all? { |t| t.errors.empty? }
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
57
58
|
def expired?
|
58
|
-
|
59
|
+
self.expires.present? && (self.expires < Time.now)
|
59
60
|
end
|
60
61
|
|
61
62
|
def expire!
|
@@ -99,7 +100,7 @@ class Notification < ActiveRecord::Base
|
|
99
100
|
self.recipients=nil
|
100
101
|
end
|
101
102
|
return temp_receipts if temp_receipts.size > 1
|
102
|
-
|
103
|
+
temp_receipts.first
|
103
104
|
end
|
104
105
|
|
105
106
|
#Returns the recipients of the Notification
|
@@ -109,25 +110,27 @@ class Notification < ActiveRecord::Base
|
|
109
110
|
self.receipts.each do |receipt|
|
110
111
|
recipients_array << receipt.receiver
|
111
112
|
end
|
112
|
-
|
113
|
+
|
114
|
+
recipients_array
|
115
|
+
else
|
116
|
+
@recipients
|
113
117
|
end
|
114
|
-
return @recipients
|
115
118
|
end
|
116
119
|
|
117
120
|
#Returns the receipt for the participant
|
118
121
|
def receipt_for(participant)
|
119
|
-
|
122
|
+
Receipt.notification(self).recipient(participant)
|
120
123
|
end
|
121
124
|
|
122
125
|
#Returns the receipt for the participant. Alias for receipt_for(participant)
|
123
126
|
def receipts_for(participant)
|
124
|
-
|
127
|
+
receipt_for(participant)
|
125
128
|
end
|
126
129
|
|
127
130
|
#Returns if the participant have read the Notification
|
128
131
|
def is_unread?(participant)
|
129
132
|
return false if participant.nil?
|
130
|
-
|
133
|
+
!self.receipt_for(participant).first.is_read
|
131
134
|
end
|
132
135
|
|
133
136
|
def is_read?(participant)
|
@@ -137,33 +140,44 @@ class Notification < ActiveRecord::Base
|
|
137
140
|
#Returns if the participant have trashed the Notification
|
138
141
|
def is_trashed?(participant)
|
139
142
|
return false if participant.nil?
|
140
|
-
|
143
|
+
self.receipt_for(participant).first.trashed
|
144
|
+
end
|
145
|
+
|
146
|
+
#Returns if the participant have deleted the Notification
|
147
|
+
def is_deleted?(participant)
|
148
|
+
return false if participant.nil?
|
149
|
+
return self.receipt_for(participant).first.deleted
|
141
150
|
end
|
142
151
|
|
143
152
|
#Mark the notification as read
|
144
153
|
def mark_as_read(participant)
|
145
154
|
return if participant.nil?
|
146
|
-
|
155
|
+
self.receipt_for(participant).mark_as_read
|
147
156
|
end
|
148
157
|
|
149
158
|
#Mark the notification as unread
|
150
159
|
def mark_as_unread(participant)
|
151
160
|
return if participant.nil?
|
152
|
-
|
161
|
+
self.receipt_for(participant).mark_as_unread
|
153
162
|
end
|
154
163
|
|
155
164
|
#Move the notification to the trash
|
156
165
|
def move_to_trash(participant)
|
157
166
|
return if participant.nil?
|
158
|
-
|
167
|
+
self.receipt_for(participant).move_to_trash
|
159
168
|
end
|
160
169
|
|
161
170
|
#Takes the notification out of the trash
|
162
171
|
def untrash(participant)
|
163
172
|
return if participant.nil?
|
164
|
-
|
173
|
+
self.receipt_for(participant).untrash
|
165
174
|
end
|
166
175
|
|
176
|
+
#Mark the notification as deleted for one of the participant
|
177
|
+
def mark_as_deleted(participant)
|
178
|
+
return if participant.nil?
|
179
|
+
return self.receipt_for(participant).mark_as_deleted
|
180
|
+
end
|
167
181
|
|
168
182
|
include ActionView::Helpers::SanitizeHelper
|
169
183
|
|
@@ -180,5 +194,4 @@ class Notification < ActiveRecord::Base
|
|
180
194
|
warn "DEPRECATION WARNING: use 'notify_object' instead of 'object' to get the object associated with the Notification"
|
181
195
|
notified_object
|
182
196
|
end
|
183
|
-
|
184
197
|
end
|
data/app/models/receipt.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
class Receipt < ActiveRecord::Base
|
2
|
+
attr_accessible :trashed, :is_read, :deleted if Mailboxer.protected_attributes?
|
3
|
+
|
2
4
|
belongs_to :notification, :validate => true, :autosave => true
|
3
5
|
belongs_to :receiver, :polymorphic => :true
|
4
6
|
belongs_to :message, :foreign_key => "notification_id"
|
5
7
|
|
6
8
|
validates_presence_of :receiver
|
7
|
-
attr_accessible :trashed, :is_read
|
8
9
|
|
9
10
|
scope :recipient, lambda { |recipient|
|
10
11
|
where(:receiver_id => recipient.id,:receiver_type => recipient.class.base_class.to_s)
|
@@ -21,8 +22,10 @@ class Receipt < ActiveRecord::Base
|
|
21
22
|
}
|
22
23
|
scope :sentbox, lambda { where(:mailbox_type => "sentbox") }
|
23
24
|
scope :inbox, lambda { where(:mailbox_type => "inbox") }
|
24
|
-
scope :trash, lambda { where(:trashed => true) }
|
25
|
+
scope :trash, lambda { where(:trashed => true, :deleted => false) }
|
25
26
|
scope :not_trash, lambda { where(:trashed => false) }
|
27
|
+
scope :deleted, lambda { where(:deleted => true) }
|
28
|
+
scope :not_deleted, lambda { where(:deleted => false) }
|
26
29
|
scope :is_read, lambda { where(:is_read => true) }
|
27
30
|
scope :is_unread, lambda { where(:is_read => false) }
|
28
31
|
|
@@ -48,6 +51,16 @@ class Receipt < ActiveRecord::Base
|
|
48
51
|
update_receipts({:trashed => false}, options)
|
49
52
|
end
|
50
53
|
|
54
|
+
#Marks the receipt as deleted
|
55
|
+
def mark_as_deleted(options={})
|
56
|
+
update_receipts({:deleted => true}, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
#Marks the receipt as not deleted
|
60
|
+
def mark_as_not_deleted(options={})
|
61
|
+
update_receipts({:deleted => false}, options)
|
62
|
+
end
|
63
|
+
|
51
64
|
#Moves all the receipts from the relation to inbox
|
52
65
|
def move_to_inbox(options={})
|
53
66
|
update_receipts({:mailbox_type => :inbox, :trashed => false}, options)
|
@@ -66,17 +79,29 @@ class Receipt < ActiveRecord::Base
|
|
66
79
|
where(options).each do |rcp|
|
67
80
|
ids << rcp.id
|
68
81
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
82
|
+
unless ids.empty?
|
83
|
+
conditions = [""].concat(ids)
|
84
|
+
condition = "id = ? "
|
85
|
+
ids.drop(1).each do
|
86
|
+
condition << "OR id = ? "
|
87
|
+
end
|
88
|
+
conditions[0] = condition
|
89
|
+
Receipt.except(:where).except(:joins).where(conditions).update_all(updates)
|
74
90
|
end
|
75
|
-
conditions[0] = condition
|
76
|
-
Receipt.except(:where).except(:joins).where(conditions).update_all(updates)
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
94
|
+
|
95
|
+
#Marks the receipt as deleted
|
96
|
+
def mark_as_deleted
|
97
|
+
update_attributes(:deleted => true)
|
98
|
+
end
|
99
|
+
|
100
|
+
#Marks the receipt as not deleted
|
101
|
+
def mark_as_not_deleted
|
102
|
+
update_attributes(:deleted => false)
|
103
|
+
end
|
104
|
+
|
80
105
|
#Marks the receipt as read
|
81
106
|
def mark_as_read
|
82
107
|
update_attributes(:is_read => true)
|
@@ -109,21 +134,19 @@ class Receipt < ActiveRecord::Base
|
|
109
134
|
|
110
135
|
#Returns the conversation associated to the receipt if the notification is a Message
|
111
136
|
def conversation
|
112
|
-
|
113
|
-
return nil
|
137
|
+
message.conversation if message.is_a? Message
|
114
138
|
end
|
115
139
|
|
116
140
|
#Returns if the participant have read the Notification
|
117
141
|
def is_unread?
|
118
|
-
|
142
|
+
!self.is_read
|
119
143
|
end
|
120
144
|
|
121
145
|
#Returns if the participant have trashed the Notification
|
122
146
|
def is_trashed?
|
123
|
-
|
147
|
+
self.trashed
|
124
148
|
end
|
125
149
|
|
126
|
-
|
127
150
|
protected
|
128
151
|
|
129
152
|
#Removes the duplicate error about not present subject from Conversation if it has been already
|
@@ -147,5 +170,4 @@ class Receipt < ActiveRecord::Base
|
|
147
170
|
integer :receiver_id
|
148
171
|
end
|
149
172
|
end
|
150
|
-
|
151
173
|
end
|