mailboxer 0.0.8 → 0.0.9
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.
- data/app/models/conversation.rb +102 -0
- data/app/models/{mailboxer_mailbox.rb → mailbox.rb} +18 -21
- data/app/models/{mailboxer_message.rb → message.rb} +6 -14
- data/app/models/{mailboxer_mail.rb → receipt.rb} +6 -14
- data/lib/generators/mailboxer/templates/migration.rb +8 -8
- data/lib/mailboxer/models/messageable.rb +90 -92
- data/mailboxer.gemspec +1 -1
- data/spec/dummy/db/migrate/{20110321231559_create_mailboxer.rb → 20110322000127_create_mailboxer.rb} +8 -8
- data/spec/integration/{mailboxer_message_and_mail_spec.rb → message_and_receipt_spec.rb} +29 -29
- data/spec/models/{mailboxer_conversation_spec.rb → conversation_spec.rb} +1 -1
- data/spec/models/mailbox_spec.rb +100 -0
- data/spec/models/mailboxer_models_messageable_spec.rb +42 -42
- data/spec/models/{mailboxer_mail_spec.rb → receipt_spec.rb} +1 -1
- metadata +12 -12
- data/app/models/mailboxer_conversation.rb +0 -106
- data/spec/models/mailboxer_mailbox_spec.rb +0 -99
@@ -0,0 +1,102 @@
|
|
1
|
+
class Conversation < ActiveRecord::Base
|
2
|
+
attr_reader :originator, :original_message, :last_sender, :last_message, :users
|
3
|
+
has_many :messages
|
4
|
+
has_many :receipts, :through => :messages
|
5
|
+
# before_create :clean
|
6
|
+
scope :participant, lambda {|participant|
|
7
|
+
joins(:receipts).select('DISTINCT conversations.*').where('receipts.receiver_id' => participant.id,'receipts.receiver_type' => participant.class.to_s).order("conversations.updated_at DESC")
|
8
|
+
}
|
9
|
+
scope :inbox, lambda {|participant|
|
10
|
+
joins(:receipts).select('DISTINCT conversations.*').where('receipts.receiver_id' => participant.id,'receipts.receiver_type' => participant.class.to_s, 'receipts.mailbox_type' => 'inbox','receipts.trashed' => false).order("conversations.updated_at DESC")
|
11
|
+
}
|
12
|
+
scope :sentbox, lambda {|participant|
|
13
|
+
joins(:receipts).select('DISTINCT conversations.*').where('receipts.receiver_id' => participant.id,'receipts.receiver_type' => participant.class.to_s, 'receipts.mailbox_type' => 'sentbox','receipts.trashed' => false).order("conversations.updated_at DESC")
|
14
|
+
}
|
15
|
+
scope :trash, lambda {|participant|
|
16
|
+
joins(:receipts).select('DISTINCT conversations.*').where('receipts.receiver_id' => participant.id,'receipts.receiver_type' => participant.class.to_s,'receipts.trashed' => true).order("conversations.updated_at DESC")
|
17
|
+
}
|
18
|
+
scope :unread, lambda {|participant|
|
19
|
+
joins(:receipts).select('DISTINCT conversations.*').where('receipts.receiver_id' => participant.id,'receipts.receiver_type' => participant.class.to_s,'receipts.read' => false).order("conversations.updated_at DESC")
|
20
|
+
}
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def total
|
24
|
+
count('DISTINCT conversations.id')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def mark_as_read(participant)
|
29
|
+
return if participant.nil?
|
30
|
+
return self.receipts(participant).mark_as_read
|
31
|
+
end
|
32
|
+
|
33
|
+
def mark_as_unread(participant)
|
34
|
+
return if participant.nil?
|
35
|
+
return self.receipts(participant).mark_as_unread
|
36
|
+
end
|
37
|
+
|
38
|
+
def move_to_trash(participant)
|
39
|
+
return if participant.nil?
|
40
|
+
return self.receipts(participant).move_to_trash
|
41
|
+
end
|
42
|
+
|
43
|
+
def untrash(participant)
|
44
|
+
return if participant.nil?
|
45
|
+
return self.receipts(participant).untrash
|
46
|
+
end
|
47
|
+
|
48
|
+
#originator of the conversation.
|
49
|
+
def originator
|
50
|
+
@orignator = self.original_message.sender if @originator.nil?
|
51
|
+
return @orignator
|
52
|
+
end
|
53
|
+
|
54
|
+
#first message of the conversation.
|
55
|
+
def original_message
|
56
|
+
@original_message = self.messages.find(:first, :order => 'created_at') if @original_message.nil?
|
57
|
+
return @original_message
|
58
|
+
end
|
59
|
+
|
60
|
+
#sender of the last message.
|
61
|
+
def last_sender
|
62
|
+
@last_sender = self.last_message.sender if @last_sender.nil?
|
63
|
+
return @last_sender
|
64
|
+
end
|
65
|
+
|
66
|
+
#last message in the conversation.
|
67
|
+
def last_message
|
68
|
+
@last_message = self.messages.find(:first, :order => 'created_at DESC') if @last_message.nil?
|
69
|
+
return @last_message
|
70
|
+
end
|
71
|
+
|
72
|
+
def receipts(participant=nil)
|
73
|
+
return Receipt.conversation(self).receiver(participant) if participant
|
74
|
+
return Receipt.conversation(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
#all users involved in the conversation.
|
78
|
+
def recipients
|
79
|
+
return last_message.get_recipients
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_recipients
|
83
|
+
return self.recipients
|
84
|
+
end
|
85
|
+
|
86
|
+
def count_messages
|
87
|
+
return Message.conversation(self).count
|
88
|
+
end
|
89
|
+
|
90
|
+
def is_participant?(participant)
|
91
|
+
return false if participant.nil?
|
92
|
+
return self.receipts(participant).count != 0
|
93
|
+
end
|
94
|
+
# protected
|
95
|
+
# #[empty method]
|
96
|
+
# #
|
97
|
+
# #this gets called before_create. Implement this if you wish to clean out illegal content such as scripts or anything that will break layout. This is left empty because what is considered illegal content varies.
|
98
|
+
# def clean
|
99
|
+
# return if subject.nil?
|
100
|
+
# #strip all illegal content here. (scripts, shit that will break layout, etc.)
|
101
|
+
# end
|
102
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
|
-
class
|
2
|
-
#this is used to filter mail by mailbox type, use the [] method rather than setting this directly.
|
1
|
+
class Mailbox
|
3
2
|
attr_accessor :type
|
4
|
-
#the user/owner of this mailbox, set when initialized.
|
5
3
|
attr_reader :messageable
|
6
|
-
#creates a new Mailbox instance with the given user and optional type.
|
7
4
|
|
8
5
|
def initialize(recipient, box = :all)
|
9
6
|
@messageable = recipient
|
@@ -15,16 +12,16 @@ class MailboxerMailbox
|
|
15
12
|
end
|
16
13
|
|
17
14
|
def conversations(options = {})
|
18
|
-
conv =
|
15
|
+
conv = Conversation.participant(@messageable)
|
19
16
|
|
20
17
|
if options[:mailbox_type].present?
|
21
18
|
case options[:mailbox_type]
|
22
19
|
when 'inbox'
|
23
|
-
conv =
|
20
|
+
conv = Conversation.inbox(@messageable)
|
24
21
|
when 'sentbox'
|
25
|
-
conv =
|
22
|
+
conv = Conversation.sentbox(@messageable)
|
26
23
|
when 'trash'
|
27
|
-
conv =
|
24
|
+
conv = Conversation.trash(@messageable)
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
@@ -50,8 +47,8 @@ class MailboxerMailbox
|
|
50
47
|
return self.conversations(options)
|
51
48
|
end
|
52
49
|
|
53
|
-
def
|
54
|
-
return
|
50
|
+
def receipts(options = {})
|
51
|
+
return Receipt.where(options).receiver(@messageable)
|
55
52
|
end
|
56
53
|
|
57
54
|
def [](mailbox_type)
|
@@ -64,28 +61,28 @@ class MailboxerMailbox
|
|
64
61
|
end
|
65
62
|
|
66
63
|
def add(msg)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@messageable.
|
73
|
-
return
|
64
|
+
msg_receipt = Receipt.new
|
65
|
+
msg_receipt.message = msg
|
66
|
+
msg_receipt.read = (msg.sender.id == @messageable.id && msg.sender.class == @messageable.class)
|
67
|
+
msg_receipt.receiver = @messageable
|
68
|
+
msg_receipt.mailbox_type = @type.to_s unless @type == :all
|
69
|
+
@messageable.receipts << msg_receipt
|
70
|
+
return msg_receipt
|
74
71
|
end
|
75
72
|
|
76
73
|
def empty_trash(options = {})
|
77
|
-
return
|
74
|
+
return false
|
78
75
|
end
|
79
76
|
|
80
77
|
def has_conversation?(conversation)
|
81
|
-
return self.
|
78
|
+
return self.receipts.conversation(converstaion).count!=0
|
82
79
|
end
|
83
80
|
|
84
81
|
def is_trashed?(conversation)
|
85
|
-
return self.
|
82
|
+
return self.receipts.trash.conversation(conversation).count!=0
|
86
83
|
end
|
87
84
|
def is_completely_trashed?(conversation)
|
88
|
-
return self.
|
85
|
+
return self.receipts.trash.conversation(conversation).count==self.receipts.conversation(conversation).count
|
89
86
|
end
|
90
87
|
|
91
88
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class Message < ActiveRecord::Base
|
2
2
|
#any additional info that needs to be sent in a message (ex. I use these to determine request types)
|
3
3
|
serialize :headers
|
4
4
|
|
@@ -9,10 +9,10 @@ class MailboxerMessage < ActiveRecord::Base
|
|
9
9
|
class_inheritable_accessor :on_deliver_clean
|
10
10
|
protected :on_deliver_clean
|
11
11
|
belongs_to :sender, :polymorphic => :true
|
12
|
-
belongs_to :
|
13
|
-
has_many :
|
12
|
+
belongs_to :conversation
|
13
|
+
has_many :receipts
|
14
14
|
scope :conversation, lambda { |conversation|
|
15
|
-
where(:
|
15
|
+
where(:conversation_id => conversation.id)
|
16
16
|
}
|
17
17
|
|
18
18
|
class << self
|
@@ -33,18 +33,10 @@ class MailboxerMessage < ActiveRecord::Base
|
|
33
33
|
|
34
34
|
def get_recipients
|
35
35
|
recipients_array = Array.new
|
36
|
-
self.
|
37
|
-
recipients_array <<
|
36
|
+
self.receipts.each do |receipt|
|
37
|
+
recipients_array << receipt.receiver
|
38
38
|
end
|
39
39
|
return recipients_array.uniq
|
40
40
|
end
|
41
41
|
|
42
|
-
def conversation
|
43
|
-
self.mailboxer_conversation
|
44
|
-
end
|
45
|
-
|
46
|
-
def mails
|
47
|
-
self.mailboxer_mails
|
48
|
-
end
|
49
|
-
|
50
42
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
-
class
|
2
|
-
belongs_to :
|
3
|
-
has_one :
|
1
|
+
class Receipt < ActiveRecord::Base
|
2
|
+
belongs_to :message
|
3
|
+
has_one :conversation, :through => :message
|
4
4
|
belongs_to :receiver, :polymorphic => :true
|
5
5
|
scope :receiver, lambda { |receiver|
|
6
6
|
where(:receiver_id => receiver.id,:receiver_type => receiver.class.to_s)
|
7
7
|
}
|
8
8
|
scope :message, lambda { |message|
|
9
|
-
where(:
|
9
|
+
where(:message_id => message.id)
|
10
10
|
}
|
11
11
|
scope :conversation, lambda { |conversation|
|
12
|
-
joins(:
|
12
|
+
joins(:message).where('messages.conversation_id' => conversation.id)
|
13
13
|
}
|
14
14
|
scope :sentbox, where(:mailbox_type => "sentbox")
|
15
15
|
scope :inbox, where(:mailbox_type => "inbox")
|
@@ -66,13 +66,5 @@ class MailboxerMail < ActiveRecord::Base
|
|
66
66
|
def move_to_sentbox
|
67
67
|
update_attributes(:mailbox_type => :sentbox, :trashed => false)
|
68
68
|
end
|
69
|
-
|
70
|
-
def message
|
71
|
-
self.mailboxer_message
|
72
|
-
end
|
73
|
-
|
74
|
-
def conversation
|
75
|
-
self.mailboxer_conversation
|
76
|
-
end
|
77
|
-
|
69
|
+
|
78
70
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class CreateMailboxer < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
|
-
create_table :
|
3
|
+
create_table :conversations do |t|
|
4
4
|
t.column :subject, :string, :default => ""
|
5
5
|
t.column :created_at, :datetime, :null => false
|
6
6
|
t.column :updated_at, :datetime, :null => false
|
7
7
|
end
|
8
|
-
create_table :
|
8
|
+
create_table :receipts do |t|
|
9
9
|
t.references :receiver, :polymorphic => true
|
10
|
-
t.column :
|
10
|
+
t.column :message_id, :integer, :null => false
|
11
11
|
t.column :read, :boolean, :default => false
|
12
12
|
t.column :trashed, :boolean, :default => false
|
13
13
|
t.column :deleted, :boolean, :default => false
|
@@ -15,12 +15,12 @@ class CreateMailboxer < ActiveRecord::Migration
|
|
15
15
|
t.column :created_at, :datetime, :null => false
|
16
16
|
t.column :updated_at, :datetime, :null => false
|
17
17
|
end
|
18
|
-
create_table :
|
18
|
+
create_table :messages do |t|
|
19
19
|
t.column :body, :text
|
20
20
|
t.column :subject, :string, :default => ""
|
21
21
|
t.column :headers, :text
|
22
22
|
t.references :sender, :polymorphic => true
|
23
|
-
t.column :
|
23
|
+
t.column :conversation_id, :integer
|
24
24
|
t.column :sent, :boolean, :default => false
|
25
25
|
t.column :draft, :boolean, :default => false
|
26
26
|
t.column :system, :boolean, :default => false
|
@@ -30,8 +30,8 @@ class CreateMailboxer < ActiveRecord::Migration
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.down
|
33
|
-
drop_table :
|
34
|
-
drop_table :
|
35
|
-
drop_table :
|
33
|
+
drop_table :receipts
|
34
|
+
drop_table :conversations
|
35
|
+
drop_table :messages
|
36
36
|
end
|
37
37
|
end
|
@@ -1,93 +1,91 @@
|
|
1
|
-
module Mailboxer
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
1
|
+
module Mailboxer
|
2
|
+
module Models
|
3
|
+
module Messageable
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def acts_as_messageable
|
10
|
+
has_many :messages
|
11
|
+
has_many :receipts, :order => 'created_at DESC', :dependent => :delete_all
|
12
|
+
|
13
|
+
include Mailboxer::Models::Messageable::InstanceMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def mailbox
|
19
|
+
@mailbox = Mailbox.new(self) if @mailbox.nil?
|
20
|
+
@mailbox.type = :all
|
21
|
+
return @mailbox
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_message(recipients, msg_body, subject = '')
|
25
|
+
convo = Conversation.create({:subject => subject})
|
26
|
+
message = Message.create({:sender => self, :conversation => convo, :body => msg_body, :subject => subject})
|
27
|
+
message.recipients = recipients.is_a?(Array) ? recipients : [recipients]
|
28
|
+
message.deliver(:inbox)
|
29
|
+
return mailbox[:sentbox] << message
|
30
|
+
end
|
31
|
+
|
32
|
+
def reply(conversation, recipients, reply_body, subject = nil)
|
33
|
+
return nil if(reply_body.blank?)
|
34
|
+
conversation.update_attribute(:updated_at, Time.now)
|
35
|
+
subject = subject || "RE: #{conversation.subject}"
|
36
|
+
response = Message.create({:sender => self, :conversation => conversation, :body => reply_body, :subject => subject})
|
37
|
+
response.recipients = recipients.is_a?(Array) ? recipients : [recipients]
|
38
|
+
response.recipients.delete(self)
|
39
|
+
response.deliver(:inbox)
|
40
|
+
return mailbox[:sentbox] << response
|
41
|
+
end
|
42
|
+
|
43
|
+
def reply_to_sender(receipt, reply_body, subject = nil)
|
44
|
+
return reply(receipt.conversation, receipt.message.sender, reply_body, subject)
|
45
|
+
end
|
46
|
+
|
47
|
+
def reply_to_all(receipt, reply_body, subject = nil)
|
48
|
+
msg = receipt.message
|
49
|
+
recipients = msg.get_recipients
|
50
|
+
return reply(receipt.conversation, recipients, reply_body, subject)
|
51
|
+
end
|
52
|
+
|
53
|
+
def reply_to_conversation(conversation, reply_body, subject = nil)
|
54
|
+
#move conversation to inbox if it is currently in the trash - doesnt make much sense replying to a trashed convo.
|
55
|
+
if(mailbox.is_trashed?(conversation))
|
56
|
+
mailbox.receipts.conversation(conversation).untrash
|
57
|
+
end
|
58
|
+
#remove self from recipients unless you are the originator of the convo
|
59
|
+
recipients = conversation.get_recipients
|
60
|
+
if(conversation.originator != self)
|
61
|
+
recipients.delete(self)
|
62
|
+
if(!recipients.include?(conversation.originator))
|
63
|
+
recipients << conversation.originator
|
64
|
+
end
|
65
|
+
end
|
66
|
+
return reply(conversation,recipients, reply_body, subject)
|
67
|
+
end
|
68
|
+
|
69
|
+
def read_message(obj)
|
70
|
+
if obj.class.to_s.eql? 'Receipt'
|
71
|
+
return obj.mark_as_read if obj.receiver == self
|
72
|
+
elsif obj.class.to_s.eql? 'Message'
|
73
|
+
receipts = obj.receipts.receiver(self)
|
74
|
+
return receipts.mark_as_read
|
75
|
+
end
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def unread_message(obj)
|
80
|
+
if obj.class.to_s.eql? 'Receipt'
|
81
|
+
return obj.mark_as_unread if obj.receiver == self
|
82
|
+
elsif obj.class.to_s.eql? 'Message'
|
83
|
+
receipts = obj.receipts.receiver(self)
|
84
|
+
return receipts.mark_as_unread
|
85
|
+
end
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
93
91
|
end
|