mailboxer 0.13.0 → 0.14.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 +10 -13
- data/Appraisals +2 -10
- data/README.md +40 -41
- data/app/builders/mailboxer/message_builder.rb +0 -8
- data/app/mailers/mailboxer/notification_mailer.rb +1 -1
- data/app/models/mailboxer/conversation.rb +15 -8
- data/app/models/mailboxer/mailbox.rb +5 -0
- data/app/models/mailboxer/message.rb +10 -9
- data/app/models/mailboxer/notification.rb +12 -21
- data/app/models/mailboxer/receipt.rb +3 -14
- data/app/views/mailboxer/notification_mailer/new_notification_email.text.erb +1 -1
- data/db/migrate/20110511145103_create_mailboxer.rb +25 -26
- data/db/migrate/20151103080417_add_delivery_tracking_info_to_mailboxer_receipts.rb +7 -0
- data/gemfiles/{rails4.0.gemfile → rails5.0.gemfile} +2 -2
- data/lib/generators/mailboxer/install_generator.rb +4 -15
- data/lib/generators/mailboxer/templates/initializer.rb +1 -1
- data/lib/generators/mailboxer/templates/mailboxer_namespacing_compatibility.rb +0 -10
- data/lib/mailboxer.rb +2 -3
- data/lib/mailboxer/engine.rb +0 -2
- data/lib/mailboxer/mail_dispatcher.rb +20 -24
- data/lib/mailboxer/models/messageable.rb +1 -6
- data/lib/mailboxer/recipient_filter.rb +17 -0
- data/lib/mailboxer/version.rb +1 -1
- data/mailboxer.gemspec +2 -10
- data/spec/dummy/config/application.rb +0 -5
- data/spec/dummy/db/migrate/20151103202534_add_missing_indices.mailboxer_engine.rb +20 -0
- data/spec/dummy/db/migrate/20151103202535_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb +8 -0
- data/spec/mailboxer/mail_dispatcher_spec.rb +15 -38
- data/spec/mailboxer/recipient_filter_spec.rb +26 -0
- data/spec/mailers/message_mailer_spec.rb +0 -30
- data/spec/models/conversation_spec.rb +12 -1
- data/spec/models/mailbox_spec.rb +6 -0
- data/spec/models/message_spec.rb +53 -17
- data/spec/models/notification_spec.rb +2 -3
- data/spec/spec_helper.rb +8 -0
- metadata +15 -26
- data/gemfiles/rails3.2.gemfile +0 -7
- data/gemfiles/rails4.1.gemfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20ef2352a667a4efe2b58ba03e9e0ec71be8c6f5
|
4
|
+
data.tar.gz: 62b56eef4d08c04fffea2050d547ea65331cd8d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1aa5bbfb3de37857cbccfee7e010f73d9bc92b03e6b221e5bbf4210af8e5fa599b9227bd4f922752d6f19342f846f328e5a3cb08b319bf818f07ba773b615ce8
|
7
|
+
data.tar.gz: 5d6dc14ece4e486dce7ff21afb63ee2d562092e29792cad1dc74fb91135f69c564853b8e939efb9702a305d5f49c168eb57e615830678bb173f45983bb86be74
|
data/.travis.yml
CHANGED
@@ -3,22 +3,19 @@ cache: bundler
|
|
3
3
|
sudo: false
|
4
4
|
|
5
5
|
rvm:
|
6
|
-
- 2.1.
|
7
|
-
|
8
|
-
|
9
|
-
include:
|
10
|
-
- rvm: 1.9.3
|
11
|
-
gemfile: gemfiles/rails4.1.gemfile
|
12
|
-
- rvm: 2.0
|
13
|
-
gemfile: gemfiles/rails4.1.gemfile
|
14
|
-
- rvm: jruby-19mode
|
15
|
-
gemfile: gemfiles/rails4.1.gemfile
|
6
|
+
- 2.1.10
|
7
|
+
- 2.2.5
|
8
|
+
- 2.3.1
|
16
9
|
|
17
10
|
gemfile:
|
18
|
-
- gemfiles/rails3.2.gemfile
|
19
|
-
- gemfiles/rails4.0.gemfile
|
20
|
-
- gemfiles/rails4.1.gemfile
|
21
11
|
- gemfiles/rails4.2.gemfile
|
12
|
+
- gemfiles/rails5.0.gemfile
|
13
|
+
|
14
|
+
matrix:
|
15
|
+
exclude:
|
16
|
+
- rvm: 2.1.10
|
17
|
+
gemfile: gemfiles/rails5.0.gemfile
|
18
|
+
|
22
19
|
env:
|
23
20
|
global:
|
24
21
|
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
data/Appraisals
CHANGED
data/README.md
CHANGED
@@ -188,7 +188,29 @@ Version 0.8.0 sees `Messageable#read` and `Messageable#unread` renamed to `mark_
|
|
188
188
|
alfa.send_message(beta, "Body", "subject")
|
189
189
|
```
|
190
190
|
|
191
|
-
### How can I
|
191
|
+
### How can I read the messages of a conversation?
|
192
|
+
|
193
|
+
As a messageable, what you receive are receipts, which are associated with the message itself. You should retrieve your receipts for the conversation and get the message associated with them.
|
194
|
+
|
195
|
+
This is done this way because receipts save the information about the relation between messageable and the messages: is it read?, is it trashed?, etc.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
#alfa gets the last conversation (chronologically, the first in the inbox)
|
199
|
+
conversation = alfa.mailbox.inbox.first
|
200
|
+
|
201
|
+
#alfa gets it receipts chronologically ordered.
|
202
|
+
receipts = conversation.receipts_for alfa
|
203
|
+
|
204
|
+
#using the receipts (i.e. in the view)
|
205
|
+
receipts.each do |receipt|
|
206
|
+
...
|
207
|
+
message = receipt.message
|
208
|
+
read = receipt.is_unread? #or message.is_unread?(alfa)
|
209
|
+
...
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
### How can I reply to a message?
|
192
214
|
|
193
215
|
```ruby
|
194
216
|
#alfa wants to reply to all in a conversation
|
@@ -205,22 +227,6 @@ alfa.reply_to_conversation(conversation, "Reply body")
|
|
205
227
|
alfa.reply_to_sender(receipt, "Reply body")
|
206
228
|
```
|
207
229
|
|
208
|
-
### How can I retrieve my conversations?
|
209
|
-
|
210
|
-
```ruby
|
211
|
-
#alfa wants to retrieve all his conversations
|
212
|
-
alfa.mailbox.conversations
|
213
|
-
|
214
|
-
#A wants to retrieve his inbox
|
215
|
-
alfa.mailbox.inbox
|
216
|
-
|
217
|
-
#A wants to retrieve his sent conversations
|
218
|
-
alfa.mailbox.sentbox
|
219
|
-
|
220
|
-
#alfa wants to retrieve his trashed conversations
|
221
|
-
alfa.mailbox.trash
|
222
|
-
```
|
223
|
-
|
224
230
|
### How can I delete a message from trash?
|
225
231
|
|
226
232
|
```ruby
|
@@ -239,10 +245,25 @@ conversation.mark_as_deleted participant
|
|
239
245
|
#* An array with any of them
|
240
246
|
alfa.mark_as_deleted conversation
|
241
247
|
```
|
248
|
+
### How can I retrieve my conversations?
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
#alfa wants to retrieve all his conversations
|
252
|
+
alfa.mailbox.conversations
|
253
|
+
|
254
|
+
#A wants to retrieve his inbox
|
255
|
+
alfa.mailbox.inbox
|
256
|
+
|
257
|
+
#A wants to retrieve his sent conversations
|
258
|
+
alfa.mailbox.sentbox
|
259
|
+
|
260
|
+
#alfa wants to retrieve his trashed conversations
|
261
|
+
alfa.mailbox.trash
|
262
|
+
```
|
242
263
|
|
243
264
|
### How can I paginate conversations?
|
244
265
|
|
245
|
-
You can use Kaminari to paginate the conversations as normal. Please, make sure you use the last version as mailboxer uses `select('DISTINCT conversations.*')` which was not respected before Kaminari 0.12.4 according to its changelog. Working
|
266
|
+
You can use Kaminari to paginate the conversations as normal. Please, make sure you use the last version as mailboxer uses `select('DISTINCT conversations.*')` which was not respected before Kaminari 0.12.4 according to its changelog. Working correctly on Kaminari 0.13.0.
|
246
267
|
|
247
268
|
```ruby
|
248
269
|
#Paginating all conversations using :page parameter and 9 per page
|
@@ -258,28 +279,6 @@ conversations = alfa.mailbox.sentbox.page(params[:page]).per(9)
|
|
258
279
|
conversations = alfa.mailbox.trash.page(params[:page]).per(9)
|
259
280
|
```
|
260
281
|
|
261
|
-
### How can I read the messages of a conversation?
|
262
|
-
|
263
|
-
As a messageable, what you receive are receipts, which are associated with the message itself. You should retrieve your receipts for the conversation a get the message associated with them.
|
264
|
-
|
265
|
-
This is done this way because receipts save the information about the relation between messageable and the messages: is it read?, is it trashed?, etc.
|
266
|
-
|
267
|
-
```ruby
|
268
|
-
#alfa gets the last conversation (chronologically, the first in the inbox)
|
269
|
-
conversation = alfa.mailbox.inbox.first
|
270
|
-
|
271
|
-
#alfa gets it receipts chronologically ordered.
|
272
|
-
receipts = conversation.receipts_for alfa
|
273
|
-
|
274
|
-
#using the receipts (i.e. in the view)
|
275
|
-
receipts.each do |receipt|
|
276
|
-
...
|
277
|
-
message = receipt.message
|
278
|
-
read = receipt.is_unread? #or message.is_unread?(alfa)
|
279
|
-
...
|
280
|
-
end
|
281
|
-
```
|
282
|
-
|
283
282
|
You can take a look at the full documentation for Mailboxer in [rubydoc.info](http://rubydoc.info/gems/mailboxer/frames).
|
284
283
|
|
285
284
|
## Do you want to test Mailboxer?
|
@@ -288,7 +287,7 @@ Thanks to [Roman Kushnir (@RKushnir)](https://github.com/RKushnir/) you can test
|
|
288
287
|
|
289
288
|
## I need a GUI!
|
290
289
|
|
291
|
-
If you need a GUI you should take a look
|
290
|
+
If you need a GUI you should take a look at these links:
|
292
291
|
|
293
292
|
* The [rails-messaging](https://github.com/frodefi/rails-messaging) project.
|
294
293
|
* The wiki page [GUI Example on a real application](https://github.com/ging/mailboxer/wiki/GUI-Example-on-a-real-application).
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Mailboxer::NotificationMailer < Mailboxer::BaseMailer
|
2
|
-
#Sends
|
2
|
+
#Sends an email for indicating a new notification to a receiver.
|
3
3
|
#It calls new_notification_email.
|
4
4
|
def send_email(notification, receiver)
|
5
5
|
new_notification_email(notification, receiver)
|
@@ -14,8 +14,8 @@ class Mailboxer::Conversation < ActiveRecord::Base
|
|
14
14
|
|
15
15
|
scope :participant, lambda {|participant|
|
16
16
|
where('mailboxer_notifications.type'=> Mailboxer::Message.name).
|
17
|
-
order(
|
18
|
-
joins(:receipts).merge(Mailboxer::Receipt.recipient(participant)).
|
17
|
+
order(updated_at: :desc).
|
18
|
+
joins(:receipts).merge(Mailboxer::Receipt.recipient(participant)).distinct
|
19
19
|
}
|
20
20
|
scope :inbox, lambda {|participant|
|
21
21
|
participant(participant).merge(Mailboxer::Receipt.inbox.not_trash.not_deleted)
|
@@ -32,6 +32,13 @@ class Mailboxer::Conversation < ActiveRecord::Base
|
|
32
32
|
scope :not_trash, lambda {|participant|
|
33
33
|
participant(participant).merge(Mailboxer::Receipt.not_trash)
|
34
34
|
}
|
35
|
+
scope :between, lambda {|participant_one, participant_two|
|
36
|
+
joins("INNER JOIN (#{Mailboxer::Notification.recipient(participant_two).to_sql}) participant_two_notifications " \
|
37
|
+
"ON participant_two_notifications.conversation_id = #{table_name}.id AND participant_two_notifications.type IN ('Mailboxer::Message')").
|
38
|
+
joins("INNER JOIN mailboxer_receipts ON mailboxer_receipts.notification_id = participant_two_notifications.id").
|
39
|
+
merge(Mailboxer::Receipt.recipient(participant_one)).
|
40
|
+
order(updated_at: :desc).distinct
|
41
|
+
}
|
35
42
|
|
36
43
|
#Mark the conversation as read for one of the participants
|
37
44
|
def mark_as_read(participant)
|
@@ -115,17 +122,17 @@ class Mailboxer::Conversation < ActiveRecord::Base
|
|
115
122
|
receipts_for(participant).any?
|
116
123
|
end
|
117
124
|
|
118
|
-
|
119
|
-
|
120
|
-
|
125
|
+
#Adds a new participant to the conversation
|
126
|
+
def add_participant(participant)
|
127
|
+
messages.each do |message|
|
121
128
|
Mailboxer::ReceiptBuilder.new({
|
122
129
|
:notification => message,
|
123
130
|
:receiver => participant,
|
124
131
|
:updated_at => message.updated_at,
|
125
132
|
:created_at => message.created_at
|
126
133
|
}).build.save
|
127
|
-
|
128
|
-
|
134
|
+
end
|
135
|
+
end
|
129
136
|
|
130
137
|
#Returns true if the participant has at least one trashed message of the conversation
|
131
138
|
def is_trashed?(participant)
|
@@ -163,7 +170,7 @@ class Mailboxer::Conversation < ActiveRecord::Base
|
|
163
170
|
end
|
164
171
|
|
165
172
|
# Creates a opt out object
|
166
|
-
# because by default all
|
173
|
+
# because by default all participants are opt in
|
167
174
|
def opt_out(participant)
|
168
175
|
return unless has_subscriber?(participant)
|
169
176
|
opt_outs.create(:unsubscriber => participant)
|
@@ -17,6 +17,11 @@ class Mailboxer::Mailbox
|
|
17
17
|
notifs
|
18
18
|
end
|
19
19
|
|
20
|
+
#Returns the conversations between messageable and other messageable
|
21
|
+
def conversations_with(other_messageable)
|
22
|
+
Mailboxer::Conversation.between(messageable, other_messageable)
|
23
|
+
end
|
24
|
+
|
20
25
|
#Returns the conversations for the messageable
|
21
26
|
#
|
22
27
|
#Options
|
@@ -2,7 +2,7 @@ class Mailboxer::Message < Mailboxer::Notification
|
|
2
2
|
attr_accessible :attachment if Mailboxer.protected_attributes?
|
3
3
|
self.table_name = :mailboxer_notifications
|
4
4
|
|
5
|
-
belongs_to :conversation, :
|
5
|
+
belongs_to :conversation, :validate => true, :autosave => true
|
6
6
|
validates_presence_of :sender
|
7
7
|
|
8
8
|
class_attribute :on_deliver_callback
|
@@ -11,7 +11,7 @@ class Mailboxer::Message < Mailboxer::Notification
|
|
11
11
|
where(:conversation_id => conversation.id)
|
12
12
|
}
|
13
13
|
|
14
|
-
mount_uploader :attachment, AttachmentUploader
|
14
|
+
mount_uploader :attachment, Mailboxer::AttachmentUploader
|
15
15
|
|
16
16
|
class << self
|
17
17
|
#Sets the on deliver callback method.
|
@@ -26,16 +26,17 @@ class Mailboxer::Message < Mailboxer::Notification
|
|
26
26
|
self.clean if should_clean
|
27
27
|
|
28
28
|
#Receiver receipts
|
29
|
-
|
29
|
+
receiver_receipts = recipients.map do |r|
|
30
|
+
receipts.build(receiver: r, mailbox_type: 'inbox', is_read: false)
|
31
|
+
end
|
30
32
|
|
31
33
|
#Sender receipt
|
32
|
-
sender_receipt =
|
33
|
-
|
34
|
-
temp_receipts << sender_receipt
|
34
|
+
sender_receipt =
|
35
|
+
receipts.build(receiver: sender, mailbox_type: 'sentbox', is_read: true)
|
35
36
|
|
36
|
-
if
|
37
|
-
|
38
|
-
Mailboxer::MailDispatcher.new(self,
|
37
|
+
if valid?
|
38
|
+
save!
|
39
|
+
Mailboxer::MailDispatcher.new(self, receiver_receipts).call
|
39
40
|
|
40
41
|
conversation.touch if reply
|
41
42
|
|
@@ -4,12 +4,11 @@ class Mailboxer::Notification < ActiveRecord::Base
|
|
4
4
|
attr_accessor :recipients
|
5
5
|
attr_accessible :body, :subject, :global, :expires if Mailboxer.protected_attributes?
|
6
6
|
|
7
|
-
belongs_to :sender, :polymorphic => :true
|
8
|
-
belongs_to :notified_object, :polymorphic => :true
|
7
|
+
belongs_to :sender, :polymorphic => :true, :required => false
|
8
|
+
belongs_to :notified_object, :polymorphic => :true, :required => false
|
9
9
|
has_many :receipts, :dependent => :destroy, :class_name => "Mailboxer::Receipt"
|
10
10
|
|
11
|
-
validates :subject, :
|
12
|
-
:length => { :maximum => Mailboxer.subject_max_length }
|
11
|
+
validates :subject, :length => { :maximum => Mailboxer.subject_max_length }
|
13
12
|
validates :body, :presence => true,
|
14
13
|
:length => { :maximum => Mailboxer.body_max_length }
|
15
14
|
|
@@ -81,11 +80,14 @@ class Mailboxer::Notification < ActiveRecord::Base
|
|
81
80
|
#Use Mailboxer::Models::Message.notify and Notification.notify_all instead.
|
82
81
|
def deliver(should_clean = true, send_mail = true)
|
83
82
|
clean if should_clean
|
84
|
-
temp_receipts = recipients.map
|
83
|
+
temp_receipts = recipients.map do |r|
|
84
|
+
receipts.build(receiver: r, mailbox_type: nil, is_read: false)
|
85
|
+
end
|
86
|
+
|
87
|
+
if valid?
|
88
|
+
Mailboxer::MailDispatcher.new(self, temp_receipts).call if send_mail
|
89
|
+
save!
|
85
90
|
|
86
|
-
if temp_receipts.all?(&:valid?)
|
87
|
-
temp_receipts.each(&:save!) #Save receipts
|
88
|
-
Mailboxer::MailDispatcher.new(self, recipients).call if send_mail
|
89
91
|
self.recipients = nil
|
90
92
|
end
|
91
93
|
|
@@ -96,7 +98,8 @@ class Mailboxer::Notification < ActiveRecord::Base
|
|
96
98
|
#Returns the recipients of the Notification
|
97
99
|
def recipients
|
98
100
|
return Array.wrap(@recipients) unless @recipients.blank?
|
99
|
-
|
101
|
+
recipients = receipts.includes(:receiver).map(&:receiver)
|
102
|
+
@recipients = Mailboxer::RecipientFilter.new(self, recipients).call
|
100
103
|
end
|
101
104
|
|
102
105
|
#Returns the receipt for the participant
|
@@ -176,16 +179,4 @@ class Mailboxer::Notification < ActiveRecord::Base
|
|
176
179
|
def sanitize(text)
|
177
180
|
::Mailboxer::Cleaner.instance.sanitize(text)
|
178
181
|
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
def build_receipt(receiver, mailbox_type, is_read = false)
|
183
|
-
Mailboxer::ReceiptBuilder.new({
|
184
|
-
:notification => self,
|
185
|
-
:mailbox_type => mailbox_type,
|
186
|
-
:receiver => receiver,
|
187
|
-
:is_read => is_read
|
188
|
-
}).build
|
189
|
-
end
|
190
|
-
|
191
182
|
end
|
@@ -2,9 +2,9 @@ class Mailboxer::Receipt < ActiveRecord::Base
|
|
2
2
|
self.table_name = :mailboxer_receipts
|
3
3
|
attr_accessible :trashed, :is_read, :deleted if Mailboxer.protected_attributes?
|
4
4
|
|
5
|
-
belongs_to :notification, :class_name => "Mailboxer::Notification"
|
6
|
-
belongs_to :receiver, :polymorphic => :true
|
7
|
-
belongs_to :message, :class_name => "Mailboxer::Message", :foreign_key => "notification_id"
|
5
|
+
belongs_to :notification, :class_name => "Mailboxer::Notification"
|
6
|
+
belongs_to :receiver, :polymorphic => :true, :required => false
|
7
|
+
belongs_to :message, :class_name => "Mailboxer::Message", :foreign_key => "notification_id", :required => false
|
8
8
|
|
9
9
|
validates_presence_of :receiver
|
10
10
|
|
@@ -30,7 +30,6 @@ class Mailboxer::Receipt < ActiveRecord::Base
|
|
30
30
|
scope :is_read, lambda { where(:is_read => true) }
|
31
31
|
scope :is_unread, lambda { where(:is_read => false) }
|
32
32
|
|
33
|
-
after_validation :remove_duplicate_errors
|
34
33
|
class << self
|
35
34
|
#Marks all the receipts from the relation as read
|
36
35
|
def mark_as_read(options={})
|
@@ -140,16 +139,6 @@ class Mailboxer::Receipt < ActiveRecord::Base
|
|
140
139
|
|
141
140
|
protected
|
142
141
|
|
143
|
-
#Removes the duplicate error about not present subject from Conversation if it has been already
|
144
|
-
#raised by Message
|
145
|
-
def remove_duplicate_errors
|
146
|
-
if errors["mailboxer_notification.conversation.subject"].present? and errors["mailboxer_notification.subject"].present?
|
147
|
-
errors["mailboxer_notification.conversation.subject"].each do |msg|
|
148
|
-
errors["mailboxer_notification.conversation.subject"].delete(msg)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
142
|
if Mailboxer.search_enabled
|
154
143
|
searchable do
|
155
144
|
text :subject, :boost => 5 do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
You have a new notification: <%= @notification.subject.html_safe? ? @notification.subject : strip_tags(@notification.subject) %>
|
2
2
|
===============================================
|
3
|
-
|
3
|
+
|
4
4
|
You have received a new notification:
|
5
5
|
|
6
6
|
-----------------------------------------------
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class CreateMailboxer < ActiveRecord::Migration
|
2
|
-
def self.up
|
2
|
+
def self.up
|
3
3
|
#Tables
|
4
|
-
|
4
|
+
#Conversations
|
5
5
|
create_table :mailboxer_conversations do |t|
|
6
6
|
t.column :subject, :string, :default => ""
|
7
7
|
t.column :created_at, :datetime, :null => false
|
8
8
|
t.column :updated_at, :datetime, :null => false
|
9
|
-
end
|
10
|
-
|
9
|
+
end
|
10
|
+
#Receipts
|
11
11
|
create_table :mailboxer_receipts do |t|
|
12
12
|
t.references :receiver, :polymorphic => true
|
13
13
|
t.column :notification_id, :integer, :null => false
|
@@ -17,8 +17,8 @@ class CreateMailboxer < ActiveRecord::Migration
|
|
17
17
|
t.column :mailbox_type, :string, :limit => 25
|
18
18
|
t.column :created_at, :datetime, :null => false
|
19
19
|
t.column :updated_at, :datetime, :null => false
|
20
|
-
end
|
21
|
-
|
20
|
+
end
|
21
|
+
#Notifications and Messages
|
22
22
|
create_table :mailboxer_notifications do |t|
|
23
23
|
t.column :type, :string
|
24
24
|
t.column :body, :text
|
@@ -33,30 +33,29 @@ class CreateMailboxer < ActiveRecord::Migration
|
|
33
33
|
t.column :created_at, :datetime, :null => false
|
34
34
|
t.boolean :global, default: false
|
35
35
|
t.datetime :expires
|
36
|
-
end
|
37
|
-
|
38
|
-
|
36
|
+
end
|
37
|
+
|
39
38
|
#Indexes
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
#Conversations
|
40
|
+
#Receipts
|
41
|
+
add_index "mailboxer_receipts","notification_id"
|
42
|
+
|
43
|
+
#Messages
|
44
|
+
add_index "mailboxer_notifications","conversation_id"
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
add_foreign_key "mailboxer_receipts", "mailboxer_notifications", :name => "receipts_on_notification_id", :column => "notification_id"
|
51
|
-
#Messages
|
52
|
-
add_foreign_key "mailboxer_notifications", "mailboxer_conversations", :name => "notifications_on_conversation_id", :column => "conversation_id"
|
46
|
+
#Foreign keys
|
47
|
+
#Conversations
|
48
|
+
#Receipts
|
49
|
+
add_foreign_key "mailboxer_receipts", "mailboxer_notifications", :name => "receipts_on_notification_id", :column => "notification_id"
|
50
|
+
#Messages
|
51
|
+
add_foreign_key "mailboxer_notifications", "mailboxer_conversations", :name => "notifications_on_conversation_id", :column => "conversation_id"
|
53
52
|
end
|
54
|
-
|
53
|
+
|
55
54
|
def self.down
|
56
|
-
#Tables
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
#Tables
|
56
|
+
remove_foreign_key "mailboxer_receipts", :name => "receipts_on_notification_id"
|
57
|
+
remove_foreign_key "mailboxer_notifications", :name => "notifications_on_conversation_id"
|
58
|
+
|
60
59
|
#Indexes
|
61
60
|
drop_table :mailboxer_receipts
|
62
61
|
drop_table :mailboxer_conversations
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class AddDeliveryTrackingInfoToMailboxerReceipts < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :mailboxer_receipts, :is_delivered, :boolean, default: false
|
4
|
+
add_column :mailboxer_receipts, :delivery_method, :string
|
5
|
+
add_column :mailboxer_receipts, :message_id, :string
|
6
|
+
end
|
7
|
+
end
|
@@ -17,20 +17,9 @@ class Mailboxer::InstallGenerator < Rails::Generators::Base #:nodoc:
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def copy_migrations
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
%w[20131206080417_add_missing_indices.rb add_missing_indices.rb]
|
25
|
-
],
|
26
|
-
migrations.each do |migration|
|
27
|
-
migration_template "../../../../db/migrate/" + migration[0], "db/migrate/" + migration[1]
|
28
|
-
end
|
29
|
-
else
|
30
|
-
require 'rake'
|
31
|
-
Rails.application.load_tasks
|
32
|
-
Rake::Task['railties:install:migrations'].reenable
|
33
|
-
Rake::Task['mailboxer_engine:install:migrations'].invoke
|
34
|
-
end
|
20
|
+
require 'rake'
|
21
|
+
Rails.application.load_tasks
|
22
|
+
Rake::Task['railties:install:migrations'].reenable
|
23
|
+
Rake::Task['mailboxer_engine:install:migrations'].invoke
|
35
24
|
end
|
36
25
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Mailboxer.setup do |config|
|
2
2
|
|
3
|
-
#Configures if
|
3
|
+
#Configures if your application uses or not email sending for Notifications and Messages
|
4
4
|
config.uses_emails = true
|
5
5
|
|
6
6
|
#Configures the default from for emails sent for Messages and Notifications
|
@@ -5,11 +5,6 @@ class MailboxerNamespacingCompatibility < ActiveRecord::Migration
|
|
5
5
|
rename_table :notifications, :mailboxer_notifications
|
6
6
|
rename_table :receipts, :mailboxer_receipts
|
7
7
|
|
8
|
-
if Rails.version < '4'
|
9
|
-
rename_index :mailboxer_notifications, :notifications_on_conversation_id, :mailboxer_notifications_on_conversation_id
|
10
|
-
rename_index :mailboxer_receipts, :receipts_on_notification_id, :mailboxer_receipts_on_notification_id
|
11
|
-
end
|
12
|
-
|
13
8
|
Mailboxer::Notification.where(type: 'Message').update_all(type: 'Mailboxer::Message')
|
14
9
|
end
|
15
10
|
|
@@ -18,11 +13,6 @@ class MailboxerNamespacingCompatibility < ActiveRecord::Migration
|
|
18
13
|
rename_table :mailboxer_notifications, :notifications
|
19
14
|
rename_table :mailboxer_receipts, :receipts
|
20
15
|
|
21
|
-
if Rails.version < '4'
|
22
|
-
rename_index :notifications, :mailboxer_notifications_on_conversation_id, :notifications_on_conversation_id
|
23
|
-
rename_index :receipts, :mailboxer_receipts_on_notification_id, :receipts_on_notification_id
|
24
|
-
end
|
25
|
-
|
26
16
|
Mailboxer::Notification.where(type: 'Mailboxer::Message').update_all(type: 'Message')
|
27
17
|
end
|
28
18
|
end
|
data/lib/mailboxer.rb
CHANGED
@@ -7,8 +7,6 @@ module Mailboxer
|
|
7
7
|
@@default_from = "no-reply@mailboxer.com"
|
8
8
|
mattr_accessor :uses_emails
|
9
9
|
@@uses_emails = true
|
10
|
-
mattr_accessor :mailer_wants_array
|
11
|
-
@@mailer_wants_array = false
|
12
10
|
mattr_accessor :search_enabled
|
13
11
|
@@search_enabled = false
|
14
12
|
mattr_accessor :search_engine
|
@@ -31,7 +29,7 @@ module Mailboxer
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def protected_attributes?
|
34
|
-
|
32
|
+
defined?(ProtectedAttributes)
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
@@ -41,3 +39,4 @@ end
|
|
41
39
|
require 'mailboxer/engine'
|
42
40
|
require 'mailboxer/cleaner'
|
43
41
|
require 'mailboxer/mail_dispatcher'
|
42
|
+
require 'mailboxer/recipient_filter'
|
data/lib/mailboxer/engine.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
module Mailboxer
|
2
2
|
class MailDispatcher
|
3
|
+
attr_reader :mailable, :receipts
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(mailable, recipients)
|
7
|
-
@mailable, @recipients = mailable, recipients
|
5
|
+
def initialize(mailable, receipts)
|
6
|
+
@mailable, @receipts = mailable, receipts
|
8
7
|
end
|
9
8
|
|
10
9
|
def call
|
11
10
|
return false unless Mailboxer.uses_emails
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
email_to = recipient.send(Mailboxer.email_method, mailable)
|
17
|
-
send_email(recipient) if email_to.present?
|
18
|
-
end
|
11
|
+
|
12
|
+
receipts.map do |receipt|
|
13
|
+
email_to = receipt.receiver.send(Mailboxer.email_method, mailable)
|
14
|
+
send_email(receipt) if email_to.present?
|
19
15
|
end
|
20
16
|
end
|
21
17
|
|
@@ -27,22 +23,22 @@ module Mailboxer
|
|
27
23
|
Mailboxer.send(method) || "#{mailable.class}Mailer".constantize
|
28
24
|
end
|
29
25
|
|
30
|
-
|
31
|
-
def filtered_recipients
|
32
|
-
return recipients unless mailable.respond_to?(:conversation)
|
33
|
-
|
34
|
-
recipients.each_with_object([]) do |recipient, array|
|
35
|
-
array << recipient if mailable.conversation.has_subscriber?(recipient)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def send_email(recipient)
|
26
|
+
def send_email(receipt)
|
40
27
|
if Mailboxer.custom_deliver_proc
|
41
|
-
Mailboxer.custom_deliver_proc.call(mailer, mailable,
|
28
|
+
Mailboxer.custom_deliver_proc.call(mailer, mailable, receipt.receiver)
|
42
29
|
else
|
43
|
-
|
44
|
-
email.respond_to?(:deliver_now) ? email.deliver_now : email.deliver
|
30
|
+
default_send_email(receipt)
|
45
31
|
end
|
46
32
|
end
|
33
|
+
|
34
|
+
def default_send_email(receipt)
|
35
|
+
mail = mailer.send_email(mailable, receipt.receiver)
|
36
|
+
mail.respond_to?(:deliver_now) ? mail.deliver_now : mail.deliver
|
37
|
+
receipt.assign_attributes(
|
38
|
+
:delivery_method => :email,
|
39
|
+
:message_id => mail.message_id
|
40
|
+
)
|
41
|
+
mail
|
42
|
+
end
|
47
43
|
end
|
48
44
|
end
|
@@ -14,12 +14,7 @@ module Mailboxer
|
|
14
14
|
|
15
15
|
included do
|
16
16
|
has_many :messages, :class_name => "Mailboxer::Message", :as => :sender
|
17
|
-
|
18
|
-
has_many :receipts, -> { order 'created_at DESC' }, :class_name => "Mailboxer::Receipt", dependent: :destroy, as: :receiver
|
19
|
-
else
|
20
|
-
# Rails 3 does it this way
|
21
|
-
has_many :receipts, :order => 'created_at DESC', :class_name => "Mailboxer::Receipt", :dependent => :destroy, :as => :receiver
|
22
|
-
end
|
17
|
+
has_many :receipts, -> { order 'created_at DESC' }, :class_name => "Mailboxer::Receipt", dependent: :destroy, as: :receiver
|
23
18
|
end
|
24
19
|
|
25
20
|
unless defined?(Mailboxer.name_method)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Mailboxer
|
2
|
+
class RecipientFilter
|
3
|
+
attr_reader :mailable, :recipients
|
4
|
+
def initialize(mailable, recipients)
|
5
|
+
@mailable, @recipients = mailable, recipients
|
6
|
+
end
|
7
|
+
|
8
|
+
# recipients can be filtered on a conversation basis
|
9
|
+
def call
|
10
|
+
return recipients unless mailable.respond_to?(:conversation)
|
11
|
+
|
12
|
+
recipients.each_with_object([]) do |recipient, array|
|
13
|
+
array << recipient if mailable.conversation.has_subscriber?(recipient)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/mailboxer/version.rb
CHANGED
data/mailboxer.gemspec
CHANGED
@@ -20,11 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
# Gem dependencies
|
22
22
|
#
|
23
|
-
# SQL foreign keys
|
24
|
-
s.add_runtime_dependency('foreigner', '>= 0.9.1')
|
25
23
|
|
26
24
|
# Development Gem dependencies
|
27
|
-
s.add_runtime_dependency('rails', '>=
|
25
|
+
s.add_runtime_dependency('rails', '>= 4.2.0')
|
28
26
|
s.add_runtime_dependency('carrierwave', '>= 0.5.8')
|
29
27
|
|
30
28
|
if RUBY_ENGINE == "rbx" && RUBY_VERSION >= "2.1.0"
|
@@ -37,13 +35,7 @@ Gem::Specification.new do |s|
|
|
37
35
|
s.add_development_dependency 'rspec-its', '~> 1.1'
|
38
36
|
s.add_development_dependency 'rspec-collection_matchers', '~> 1.1'
|
39
37
|
s.add_development_dependency('appraisal', '~> 1.0.0')
|
40
|
-
s.add_development_dependency('shoulda-matchers')
|
41
|
-
# Fixtures
|
42
|
-
#if RUBY_VERSION >= '1.9.2'
|
43
|
-
# s.add_development_dependency('factory_girl', '>= 3.0.0')
|
44
|
-
#else
|
45
|
-
#s.add_development_dependency('factory_girl', '~> 2.6.0')
|
46
|
-
#end
|
38
|
+
s.add_development_dependency('shoulda-matchers', '~> 2')
|
47
39
|
s.add_development_dependency('factory_girl', '~> 2.6.0')
|
48
40
|
# Population
|
49
41
|
s.add_development_dependency('forgery', '>= 0.3.6')
|
@@ -7,9 +7,6 @@ require "mailboxer"
|
|
7
7
|
|
8
8
|
module Dummy
|
9
9
|
class Application < Rails::Application
|
10
|
-
def rails_more_than_4_2?
|
11
|
-
Gem::Version.new(Rails.version) >= Gem::Version.new('4.2.0')
|
12
|
-
end
|
13
10
|
# Settings in config/environments/* take precedence over those specified here.
|
14
11
|
# Application configuration should go into files in config/initializers
|
15
12
|
# -- all .rb files in that directory are automatically loaded.
|
@@ -40,8 +37,6 @@ module Dummy
|
|
40
37
|
|
41
38
|
# Configure sensitive parameters which will be filtered from the log file.
|
42
39
|
config.filter_parameters += [:password]
|
43
|
-
config.active_record.raise_in_transactional_callbacks = true if rails_more_than_4_2?
|
44
|
-
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# This migration comes from mailboxer_engine (originally 20131206080417)
|
2
|
+
class AddMissingIndices < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
# We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63
|
5
|
+
# characters limitation.
|
6
|
+
add_index :mailboxer_conversation_opt_outs, [:unsubscriber_id, :unsubscriber_type],
|
7
|
+
name: 'index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type'
|
8
|
+
add_index :mailboxer_conversation_opt_outs, :conversation_id
|
9
|
+
|
10
|
+
add_index :mailboxer_notifications, :type
|
11
|
+
add_index :mailboxer_notifications, [:sender_id, :sender_type]
|
12
|
+
|
13
|
+
# We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63
|
14
|
+
# characters limitation.
|
15
|
+
add_index :mailboxer_notifications, [:notified_object_id, :notified_object_type],
|
16
|
+
name: 'index_mailboxer_notifications_on_notified_object_id_and_type'
|
17
|
+
|
18
|
+
add_index :mailboxer_receipts, [:receiver_id, :receiver_type]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# This migration comes from mailboxer_engine (originally 20151103080417)
|
2
|
+
class AddDeliveryTrackingInfoToMailboxerReceipts < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
add_column :mailboxer_receipts, :is_delivered, :boolean, default: false
|
5
|
+
add_column :mailboxer_receipts, :delivery_method, :string
|
6
|
+
add_column :mailboxer_receipts, :message_id, :string
|
7
|
+
end
|
8
|
+
end
|
@@ -2,12 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mailboxer::MailDispatcher do
|
4
4
|
|
5
|
-
subject(:instance) { described_class.new(mailable,
|
5
|
+
subject(:instance) { described_class.new(mailable, receipts) }
|
6
6
|
|
7
7
|
let(:mailable) { Mailboxer::Notification.new }
|
8
|
-
let(:recipient1) { double 'recipient1', mailboxer_email: ''
|
9
|
-
let(:recipient2) { double 'recipient2', mailboxer_email: 'foo@bar.com'
|
10
|
-
let(:
|
8
|
+
let(:recipient1) { double 'recipient1', id: 1, mailboxer_email: '' }
|
9
|
+
let(:recipient2) { double 'recipient2', id: 2, mailboxer_email: 'foo@bar.com'}
|
10
|
+
let(:receipt1) { double 'receipt1', id: 1, receiver: recipient1 }
|
11
|
+
let(:receipt2) { double 'receipt2', id: 2, receiver: recipient2 }
|
12
|
+
|
13
|
+
let(:receipts) { [ receipt1, receipt2 ] }
|
11
14
|
|
12
15
|
describe "call" do
|
13
16
|
context "no emails" do
|
@@ -16,19 +19,10 @@ describe Mailboxer::MailDispatcher do
|
|
16
19
|
its(:call) { should be false }
|
17
20
|
end
|
18
21
|
|
19
|
-
context "mailer
|
20
|
-
before { Mailboxer.mailer_wants_array = true }
|
21
|
-
after { Mailboxer.mailer_wants_array = false }
|
22
|
+
context "mailer doesn't want array" do
|
22
23
|
it 'sends collection' do
|
23
|
-
expect(subject).
|
24
|
-
subject.
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "mailer doesnt want array" do
|
29
|
-
it 'sends collection' do
|
30
|
-
expect(subject).not_to receive(:send_email).with(recipient1) #email is blank
|
31
|
-
expect(subject).to receive(:send_email).with(recipient2)
|
24
|
+
expect(subject).not_to receive(:send_email).with(receipt1) #email is blank
|
25
|
+
expect(subject).to receive(:send_email).with(receipt2)
|
32
26
|
subject.call
|
33
27
|
end
|
34
28
|
end
|
@@ -49,24 +43,25 @@ describe Mailboxer::MailDispatcher do
|
|
49
43
|
after { Mailboxer.custom_deliver_proc = nil }
|
50
44
|
it "triggers proc" do
|
51
45
|
expect(my_proc).to receive(:call).with(mailer, mailable, recipient1)
|
52
|
-
subject.send :send_email,
|
46
|
+
subject.send :send_email, receipt1
|
53
47
|
end
|
54
48
|
end
|
55
49
|
|
56
50
|
context "without custom_deliver_proc" do
|
57
|
-
let(:email) { double :email }
|
51
|
+
let(:email) { double :email, message_id: '123@local.com' }
|
58
52
|
|
59
53
|
it "triggers standard deliver chain" do
|
60
54
|
expect(mailer).to receive(:send_email).with(mailable, recipient1).and_return email
|
55
|
+
expect(receipt1).to receive(:assign_attributes).with({:delivery_method=>:email, :message_id=>"123@local.com"}).and_return email
|
61
56
|
expect(email).to receive :deliver
|
62
57
|
|
63
|
-
subject.send :send_email,
|
58
|
+
subject.send :send_email, receipt1
|
64
59
|
end
|
65
60
|
end
|
66
61
|
end
|
67
62
|
|
68
63
|
describe "mailer" do
|
69
|
-
let(:
|
64
|
+
let(:receipts) { [] }
|
70
65
|
|
71
66
|
context "mailable is a Message" do
|
72
67
|
let(:mailable) { Mailboxer::Notification.new }
|
@@ -93,22 +88,4 @@ describe Mailboxer::MailDispatcher do
|
|
93
88
|
end
|
94
89
|
end
|
95
90
|
end
|
96
|
-
|
97
|
-
describe "filtered_recipients" do
|
98
|
-
context "responds to conversation" do
|
99
|
-
let(:conversation) { double 'conversation' }
|
100
|
-
let(:mailable) { double 'mailable', :conversation => conversation }
|
101
|
-
before(:each) do
|
102
|
-
expect(conversation).to receive(:has_subscriber?).with(recipient1).and_return false
|
103
|
-
expect(conversation).to receive(:has_subscriber?).with(recipient2).and_return true
|
104
|
-
end
|
105
|
-
|
106
|
-
its(:filtered_recipients){ should eq [recipient2] }
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'doesnt respond to conversation' do
|
110
|
-
let(:mailable) { double 'mailable' }
|
111
|
-
its(:filtered_recipients){ should eq recipients }
|
112
|
-
end
|
113
|
-
end
|
114
91
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mailboxer::RecipientFilter do
|
4
|
+
subject(:instance) { described_class.new(mailable, recipients) }
|
5
|
+
let(:recipient1) { double 'recipient1', id: 1, mailboxer_email: '' }
|
6
|
+
let(:recipient2) { double 'recipient2', id: 2, mailboxer_email: 'foo@bar.com'}
|
7
|
+
let(:recipients) { [ recipient1, recipient2 ] }
|
8
|
+
|
9
|
+
describe "call" do
|
10
|
+
context "responds to conversation" do
|
11
|
+
let(:conversation) { double 'conversation' }
|
12
|
+
let(:mailable) { double 'mailable', :conversation => conversation }
|
13
|
+
before(:each) do
|
14
|
+
expect(conversation).to receive(:has_subscriber?).with(recipient1).and_return false
|
15
|
+
expect(conversation).to receive(:has_subscriber?).with(recipient2).and_return true
|
16
|
+
end
|
17
|
+
|
18
|
+
its(:call){ should eq [recipient2] }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'doesnt respond to conversation' do
|
22
|
+
let(:mailable) { double 'mailable' }
|
23
|
+
its(:call){ should eq recipients }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -60,36 +60,6 @@ describe Mailboxer::MessageMailer do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
|
-
|
64
|
-
context "when mailer_wants_array is false" do
|
65
|
-
it_behaves_like 'message_mailer'
|
66
|
-
end
|
67
|
-
|
68
|
-
context "mailer_wants_array is true" do
|
69
|
-
class ArrayMailer < Mailboxer::MessageMailer
|
70
|
-
default template_path: 'mailboxer/message_mailer'
|
71
|
-
|
72
|
-
def new_message_email(message, receivers)
|
73
|
-
receivers.each { |receiver| super(message, receiver) if receiver.mailboxer_email(message).present? }
|
74
|
-
end
|
75
|
-
|
76
|
-
def reply_message_email(message, receivers)
|
77
|
-
receivers.each { |receiver| super(message, receiver) if receiver.mailboxer_email(message).present? }
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
before :all do
|
82
|
-
Mailboxer.mailer_wants_array = true
|
83
|
-
Mailboxer.message_mailer = ArrayMailer
|
84
|
-
end
|
85
|
-
|
86
|
-
after :all do
|
87
|
-
Mailboxer.mailer_wants_array = false
|
88
|
-
Mailboxer.message_mailer = Mailboxer::MessageMailer
|
89
|
-
end
|
90
|
-
|
91
|
-
it_behaves_like 'message_mailer'
|
92
|
-
end
|
93
63
|
end
|
94
64
|
|
95
65
|
def print_emails
|
@@ -13,7 +13,7 @@ describe Mailboxer::Conversation do
|
|
13
13
|
let!(:conversation) { message1.conversation }
|
14
14
|
|
15
15
|
it { should validate_presence_of :subject }
|
16
|
-
it { should
|
16
|
+
it { should validate_length_of(:subject).is_at_most(Mailboxer.subject_max_length) }
|
17
17
|
|
18
18
|
it "should have proper original message" do
|
19
19
|
expect(conversation.original_message).to eq message1
|
@@ -118,6 +118,17 @@ describe Mailboxer::Conversation do
|
|
118
118
|
expect(Mailboxer::Conversation.unread(participant)).to eq [unread_conversation]
|
119
119
|
end
|
120
120
|
end
|
121
|
+
|
122
|
+
describe ".between" do
|
123
|
+
it "finds conversations where two participants participate" do
|
124
|
+
expect(Mailboxer::Conversation.between(entity1, participant)).to eq [sentbox_conversation, inbox_conversation]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "does not find conversations if the participants have not interacted yet" do
|
128
|
+
expect(Mailboxer::Conversation.between(participant, entity2)).to eq []
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
121
132
|
end
|
122
133
|
|
123
134
|
describe "#is_completely_trashed?" do
|
data/spec/models/mailbox_spec.rb
CHANGED
@@ -14,6 +14,12 @@ describe Mailboxer::Mailbox do
|
|
14
14
|
@conversation = @message1.conversation
|
15
15
|
end
|
16
16
|
|
17
|
+
it "should return conversations between two entities" do
|
18
|
+
assert @entity1.mailbox.conversations_with(@entity2)
|
19
|
+
|
20
|
+
expect(@entity1.mailbox.conversations_with(@entity2)).to eq [@conversation]
|
21
|
+
end
|
22
|
+
|
17
23
|
it "should return all conversations" do
|
18
24
|
@conv2 = @entity1.send_message(@entity2,"Body","Subject").conversation
|
19
25
|
@conv3 = @entity2.send_message(@entity1,"Body","Subject").conversation
|
data/spec/models/message_spec.rb
CHANGED
@@ -1,30 +1,66 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Mailboxer::Message do
|
4
|
-
|
5
4
|
before do
|
5
|
+
ActionMailer::Base.deliveries.clear
|
6
6
|
@entity1 = FactoryGirl.create(:user)
|
7
7
|
@entity2 = FactoryGirl.create(:user)
|
8
|
-
@receipt1 = @entity1.send_message(@entity2,"Body","Subject")
|
9
|
-
@receipt2 = @entity2.reply_to_all(@receipt1,"Reply body 1")
|
10
|
-
@receipt3 = @entity1.reply_to_all(@receipt2,"Reply body 2")
|
11
|
-
@receipt4 = @entity2.reply_to_all(@receipt3,"Reply body 3")
|
12
|
-
@message1 = @receipt1.notification
|
13
|
-
@message4 = @receipt4.notification
|
14
|
-
@conversation = @message1.conversation
|
15
8
|
end
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
10
|
+
context "with errors" do
|
11
|
+
describe "empty subject" do
|
12
|
+
before do
|
13
|
+
@receipt1 = @entity1.send_message(@entity2,"Body","")
|
14
|
+
@message1 = @receipt1.notification
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should add errors to the created notification" do
|
18
|
+
errors = @message1.errors['conversation.subject']
|
19
|
+
|
20
|
+
expect(errors).to eq(["can't be blank"])
|
21
|
+
end
|
22
|
+
end
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
context "after send" do
|
26
|
+
|
27
|
+
before do
|
28
|
+
ActionMailer::Base.deliveries.clear
|
29
|
+
@entity1 = FactoryGirl.create(:user)
|
30
|
+
@entity2 = FactoryGirl.create(:user)
|
31
|
+
@receipt1 = @entity1.send_message(@entity2,"Body","Subject")
|
32
|
+
@message1 = @receipt1.notification
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to be marked as deleted" do
|
36
|
+
expect(@receipt1.deleted).to be false
|
37
|
+
@message1.mark_as_deleted @entity1
|
38
|
+
expect(@message1.is_deleted?(@entity1)).to be true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "creates a conversation" do
|
42
|
+
expect(@message1.conversation).to eq(Mailboxer::Conversation.last)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should send email only to receivers" do
|
46
|
+
expect(ActionMailer::Base.deliveries.count).to eq 1
|
47
|
+
end
|
48
|
+
|
49
|
+
context "and multiple replies" do
|
50
|
+
before do
|
51
|
+
@receipt2 = @entity2.reply_to_all(@receipt1,"Reply body 1")
|
52
|
+
@receipt3 = @entity1.reply_to_all(@receipt2,"Reply body 2")
|
53
|
+
@receipt4 = @entity2.reply_to_all(@receipt3,"Reply body 3")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have right recipients" do
|
57
|
+
expect(@receipt1.notification.recipients.count).to eq 2
|
58
|
+
expect(@receipt2.notification.recipients.count).to eq 2
|
59
|
+
expect(@receipt3.notification.recipients.count).to eq 2
|
60
|
+
expect(@receipt4.notification.recipients.count).to eq 2
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
28
64
|
end
|
29
65
|
|
30
66
|
end
|
@@ -8,11 +8,10 @@ describe Mailboxer::Notification do
|
|
8
8
|
@entity3 = FactoryGirl.create(:user)
|
9
9
|
end
|
10
10
|
|
11
|
-
it { should validate_presence_of :subject }
|
12
11
|
it { should validate_presence_of :body }
|
13
12
|
|
14
|
-
it { should
|
15
|
-
it { should
|
13
|
+
it { should validate_length_of(:subject).is_at_most(Mailboxer.subject_max_length) }
|
14
|
+
it { should validate_length_of(:body).is_at_most(Mailboxer.body_max_length) }
|
16
15
|
|
17
16
|
it "should notify one user" do
|
18
17
|
@entity1.notify("Subject", "Body")
|
data/spec/spec_helper.rb
CHANGED
@@ -30,6 +30,14 @@ Dir["#{File.dirname(__FILE__)}/factories/*.rb"].each {|f| require f}
|
|
30
30
|
|
31
31
|
# Shoulda Matchers
|
32
32
|
require 'shoulda/matchers'
|
33
|
+
if Shoulda::Matchers.respond_to?(:configure)
|
34
|
+
Shoulda::Matchers.configure do |config|
|
35
|
+
config.integrate do |with|
|
36
|
+
with.test_framework :rspec
|
37
|
+
with.library :rails
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
33
41
|
|
34
42
|
RSpec.configure do |config|
|
35
43
|
# Remove this line if you don't want RSpec's should and should_not
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mailboxer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eduardo Casanova Cuesta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: foreigner
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.9.1
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 0.9.1
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rails
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - ">="
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
19
|
+
version: 4.2.0
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
24
|
- - ">="
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
26
|
+
version: 4.2.0
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: carrierwave
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,16 +98,16 @@ dependencies:
|
|
112
98
|
name: shoulda-matchers
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
|
-
- - "
|
101
|
+
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
103
|
+
version: '2'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
|
-
- - "
|
108
|
+
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
110
|
+
version: '2'
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: factory_girl
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,10 +209,9 @@ files:
|
|
223
209
|
- db/migrate/20110511145103_create_mailboxer.rb
|
224
210
|
- db/migrate/20131206080416_add_conversation_optout.rb
|
225
211
|
- db/migrate/20131206080417_add_missing_indices.rb
|
226
|
-
-
|
227
|
-
- gemfiles/rails4.0.gemfile
|
228
|
-
- gemfiles/rails4.1.gemfile
|
212
|
+
- db/migrate/20151103080417_add_delivery_tracking_info_to_mailboxer_receipts.rb
|
229
213
|
- gemfiles/rails4.2.gemfile
|
214
|
+
- gemfiles/rails5.0.gemfile
|
230
215
|
- lib/generators/mailboxer/install_generator.rb
|
231
216
|
- lib/generators/mailboxer/namespacing_compatibility_generator.rb
|
232
217
|
- lib/generators/mailboxer/templates/initializer.rb
|
@@ -237,6 +222,7 @@ files:
|
|
237
222
|
- lib/mailboxer/engine.rb
|
238
223
|
- lib/mailboxer/mail_dispatcher.rb
|
239
224
|
- lib/mailboxer/models/messageable.rb
|
225
|
+
- lib/mailboxer/recipient_filter.rb
|
240
226
|
- lib/mailboxer/version.rb
|
241
227
|
- mailboxer.gemspec
|
242
228
|
- spec/dummy/.gitignore
|
@@ -274,6 +260,8 @@ files:
|
|
274
260
|
- spec/dummy/db/migrate/20110306015107_create_cylons.rb
|
275
261
|
- spec/dummy/db/migrate/20120305103200_create_mailboxer.rb
|
276
262
|
- spec/dummy/db/migrate/20131206080416_add_conversation_optout.rb
|
263
|
+
- spec/dummy/db/migrate/20151103202534_add_missing_indices.mailboxer_engine.rb
|
264
|
+
- spec/dummy/db/migrate/20151103202535_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb
|
277
265
|
- spec/dummy/db/schema.rb
|
278
266
|
- spec/dummy/public/404.html
|
279
267
|
- spec/dummy/public/422.html
|
@@ -289,6 +277,7 @@ files:
|
|
289
277
|
- spec/integration/message_and_receipt_spec.rb
|
290
278
|
- spec/integration/navigation_spec.rb
|
291
279
|
- spec/mailboxer/mail_dispatcher_spec.rb
|
280
|
+
- spec/mailboxer/recipient_filter_spec.rb
|
292
281
|
- spec/mailboxer_spec.rb
|
293
282
|
- spec/mailers/message_mailer_spec.rb
|
294
283
|
- spec/mailers/notification_mailer_spec.rb
|
@@ -320,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
320
309
|
version: '0'
|
321
310
|
requirements: []
|
322
311
|
rubyforge_project:
|
323
|
-
rubygems_version: 2.
|
312
|
+
rubygems_version: 2.5.1
|
324
313
|
signing_key:
|
325
314
|
specification_version: 4
|
326
315
|
summary: Messaging system for rails apps.
|
data/gemfiles/rails3.2.gemfile
DELETED