has_messages_huacnlee 0.4.1 → 0.4.2
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/{README.rdoc → README.md} +57 -53
- data/init.rb +1 -1
- data/lib/generators/has_messages/templates/001_create_messages.rb +5 -2
- data/lib/generators/has_messages/templates/002_create_message_recipients.rb +3 -2
- data/lib/has_messages.rb +41 -88
- data/lib/has_messages/models/message_recipient.rb +1 -1
- data/lib/has_messages_huacnlee.rb +1 -0
- metadata +41 -73
- data/test/app_root/app/models/user.rb +0 -3
- data/test/app_root/config/environment.rb +0 -9
- data/test/app_root/db/migrate/001_create_users.rb +0 -11
- data/test/app_root/db/migrate/002_migrate_has_messages_to_version_2.rb +0 -13
- data/test/factory.rb +0 -58
- data/test/functional/has_messages_test.rb +0 -140
- data/test/test_helper.rb +0 -13
- data/test/unit/message_recipient_test.rb +0 -449
- data/test/unit/message_test.rb +0 -465
data/{README.rdoc → README.md}
RENAMED
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# has_messages
|
|
2
2
|
|
|
3
3
|
+has_messages+ demonstrates a reference implementation for sending messages between users.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
API
|
|
8
|
-
|
|
9
|
-
* http://rdoc.info/projects/pluginaweek/has_messages
|
|
10
|
-
|
|
11
|
-
Bugs
|
|
12
|
-
|
|
13
|
-
* http://pluginaweek.lighthouseapp.com/projects/13274-has_messages
|
|
14
|
-
|
|
15
|
-
Development
|
|
16
|
-
|
|
17
|
-
* http://github.com/pluginaweek/has_messages
|
|
18
|
-
|
|
19
|
-
Source
|
|
20
|
-
|
|
21
|
-
* git://github.com/pluginaweek/has_messages.git
|
|
22
|
-
|
|
23
|
-
== Description
|
|
5
|
+
## Description
|
|
24
6
|
|
|
25
7
|
Messaging between users is fairly common in web applications, especially those
|
|
26
8
|
that support social networking. Messaging doesn't necessarily need to be
|
|
@@ -31,82 +13,104 @@ Designing and building a framework that supports this can be complex and takes
|
|
|
31
13
|
away from the business focus. This plugin can help ease that process by
|
|
32
14
|
demonstrating a reference implementation of these features.
|
|
33
15
|
|
|
34
|
-
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
35
19
|
|
|
36
|
-
|
|
20
|
+
In your Gemfile:
|
|
37
21
|
|
|
38
|
-
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'has_messages_huacnlee'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`has_messages` requires additional database tables to work. You can generate
|
|
39
27
|
a migration for these tables like so:
|
|
40
28
|
|
|
41
|
-
|
|
29
|
+
```bash
|
|
30
|
+
$ rails g has_messages
|
|
31
|
+
```
|
|
42
32
|
|
|
43
33
|
Then simply migrate your database:
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
```bash
|
|
36
|
+
$ rake db:migrate
|
|
37
|
+
```
|
|
46
38
|
|
|
47
39
|
=== Adding message support
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
```ruby
|
|
42
|
+
class User < ActiveRecord::Base
|
|
43
|
+
has_messages
|
|
44
|
+
end
|
|
45
|
+
```
|
|
52
46
|
|
|
53
47
|
This will build the following associations:
|
|
48
|
+
|
|
54
49
|
* +messages+
|
|
55
50
|
* +unsent_messages+
|
|
56
51
|
* +sent_messages+
|
|
57
52
|
* +received_messages+
|
|
58
53
|
|
|
59
54
|
If you have more specific needs, you can create the same associations manually
|
|
60
|
-
that
|
|
55
|
+
that `has_messages` builds. See `HasMessages::MacroMethods#has_messages`
|
|
61
56
|
for more information about the asssociations that are generated from this macro.
|
|
62
57
|
|
|
63
|
-
|
|
58
|
+
### Creating new messages
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
```ruby
|
|
61
|
+
message = user.messages.build
|
|
62
|
+
message.to user1, user2
|
|
63
|
+
message.subject = 'Hey!'
|
|
64
|
+
message.body = 'Does anyone want to go out tonight?'
|
|
65
|
+
message.deliver
|
|
66
|
+
```
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
### Replying to messages
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
```ruby
|
|
71
|
+
reply = message.reply_to_all
|
|
72
|
+
reply.body = "I'd love to go out!"
|
|
73
|
+
reply.deliver
|
|
74
|
+
```
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
### Forwarding messages
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
```ruby
|
|
79
|
+
forward = message.forward
|
|
80
|
+
forward.body = 'Interested?'
|
|
81
|
+
forward.deliver
|
|
82
|
+
```
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
### Processing messages asynchronously
|
|
84
85
|
|
|
85
86
|
In addition to delivering messages immediately, you can also *queue* messages so
|
|
86
87
|
that an external application processes and delivers them. This is especially
|
|
87
88
|
useful for messages that need to be sent outside of the confines of the application.
|
|
88
89
|
|
|
89
90
|
To queue messages for external processing, you can use the +queue+ event,
|
|
90
|
-
rather than
|
|
91
|
+
rather than `deliver`. This will indicate to any external processes that
|
|
91
92
|
the message is ready to be sent.
|
|
92
93
|
|
|
93
94
|
To process queued emails, you need an external cron job that checks and sends
|
|
94
95
|
them like so:
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
```ruby
|
|
98
|
+
Message.with_state('queued').each do |message|
|
|
99
|
+
message.deliver
|
|
100
|
+
end
|
|
101
|
+
```
|
|
99
102
|
|
|
100
|
-
|
|
103
|
+
## Testing
|
|
101
104
|
|
|
102
105
|
Before you can run any tests, the following gem must be installed:
|
|
103
106
|
* plugin_test_helper[http://github.com/pluginaweek/plugin_test_helper]
|
|
104
107
|
|
|
105
108
|
To run against a specific version of Rails:
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
```bash
|
|
111
|
+
$ rake test
|
|
112
|
+
```
|
|
113
|
+
## Dependencies
|
|
110
114
|
|
|
111
|
-
* Rails 2.
|
|
115
|
+
* Rails 3.2.x
|
|
112
116
|
* state_machine[http://github.com/pluginaweek/state_machine]
|
data/init.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "has_messages"
|
|
@@ -3,12 +3,15 @@ class CreateMessages < ActiveRecord::Migration
|
|
|
3
3
|
create_table :messages do |t|
|
|
4
4
|
t.references :sender, :polymorphic => true, :null => false
|
|
5
5
|
t.text :subject, :body
|
|
6
|
-
t.string :state, :null => false
|
|
6
|
+
t.string :state, :null => false, :length => 10
|
|
7
7
|
t.datetime :hidden_at
|
|
8
|
-
t.string :type
|
|
8
|
+
t.string :type, :length => 20
|
|
9
9
|
t.belongs_to :original_message
|
|
10
10
|
t.timestamps
|
|
11
11
|
end
|
|
12
|
+
add_index :messages, [:sender_type,:sender_id]
|
|
13
|
+
add_index :messages, :hidden_at
|
|
14
|
+
add_index :messages, :state
|
|
12
15
|
end
|
|
13
16
|
|
|
14
17
|
def self.down
|
|
@@ -3,11 +3,12 @@ class CreateMessageRecipients < ActiveRecord::Migration
|
|
|
3
3
|
create_table :message_recipients do |t|
|
|
4
4
|
t.references :message, :null => false
|
|
5
5
|
t.references :receiver, :polymorphic => true, :null => false
|
|
6
|
-
t.string :kind, :null => false
|
|
6
|
+
t.string :kind, :null => false, :length => 20
|
|
7
7
|
t.integer :position
|
|
8
|
-
t.string :state, :null => false
|
|
8
|
+
t.string :state, :null => false, :length => 10
|
|
9
9
|
t.datetime :hidden_at
|
|
10
10
|
end
|
|
11
|
+
add_index :message_recipients, [:receiver_type, :receiver_id]
|
|
11
12
|
add_index :message_recipients, [:message_id, :kind, :position], :unique => true
|
|
12
13
|
end
|
|
13
14
|
|
data/lib/has_messages.rb
CHANGED
|
@@ -2,101 +2,54 @@ require 'state_machine'
|
|
|
2
2
|
|
|
3
3
|
# Adds a generic implementation for sending messages between users
|
|
4
4
|
module HasMessages
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# message.subject = 'Hello'
|
|
20
|
-
# message.body = 'How are you?'
|
|
21
|
-
# message.to User.find(456)
|
|
22
|
-
# message.save
|
|
23
|
-
# message.deliver
|
|
24
|
-
#
|
|
25
|
-
# == Drafts
|
|
26
|
-
#
|
|
27
|
-
# You can get the drafts for a particular user by using the +unsent_messages+
|
|
28
|
-
# helper method. This will find all messages in the "unsent" state. For example,
|
|
29
|
-
#
|
|
30
|
-
# user = User.find(123)
|
|
31
|
-
# user.unsent_messages
|
|
32
|
-
#
|
|
33
|
-
# You can also get at the messages that *have* been sent, using the +sent_messages+
|
|
34
|
-
# helper method. For example,
|
|
35
|
-
#
|
|
36
|
-
# user = User.find(123)
|
|
37
|
-
# user.sent_messages
|
|
38
|
-
def has_messages
|
|
39
|
-
has_many :messages,
|
|
40
|
-
:as => :sender,
|
|
41
|
-
:class_name => 'Message',
|
|
42
|
-
:conditions => {:hidden_at => nil},
|
|
43
|
-
:order => 'messages.created_at DESC'
|
|
44
|
-
has_many :received_messages,
|
|
45
|
-
:as => :receiver,
|
|
46
|
-
:class_name => 'MessageRecipient',
|
|
47
|
-
:include => :message,
|
|
48
|
-
:conditions => ['message_recipients.hidden_at IS NULL AND messages.state = ?', 'sent'],
|
|
49
|
-
:order => 'messages.created_at DESC'
|
|
50
|
-
# has_many :received_message_threads,
|
|
51
|
-
# :as => :receiver,
|
|
52
|
-
# :class_name => 'MessageRecipient',
|
|
53
|
-
# :include => :message,
|
|
54
|
-
# :conditions => ['message_recipients.hidden_at IS NULL AND messages.state = ? and messages.original_message_id IS NOT NULL', 'sent'],
|
|
55
|
-
# :group => 'messages.original_message_id',
|
|
56
|
-
# :order => 'messages.created_at DESC'
|
|
57
|
-
|
|
58
|
-
include HasMessages::InstanceMethods
|
|
59
|
-
end
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
has_many :messages,
|
|
9
|
+
:as => :sender,
|
|
10
|
+
:class_name => 'Message',
|
|
11
|
+
:conditions => {:hidden_at => nil},
|
|
12
|
+
:order => 'messages.id DESC'
|
|
13
|
+
has_many :received_messages,
|
|
14
|
+
:as => :receiver,
|
|
15
|
+
:class_name => 'MessageRecipient',
|
|
16
|
+
:include => :message,
|
|
17
|
+
:conditions => ['message_recipients.hidden_at IS NULL AND messages.state = ?', 'sent'],
|
|
18
|
+
:order => 'messages.id DESC'
|
|
60
19
|
end
|
|
61
20
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Returns the most recent message of each thread
|
|
76
|
-
def last_received_message_per_thread
|
|
77
|
-
MessageRecipient.find_all_by_receiver_id(id, :order => 'id desc', :joins => :message, :conditions => 'message_recipients.hidden_at is null', :group => 'COALESCE(original_message_id,messages.id)')
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def conversations
|
|
81
|
-
(messages + received_messages.map(&:message)).compact.uniq
|
|
82
|
-
end
|
|
21
|
+
# Composed messages that have not yet been sent. These consists of all
|
|
22
|
+
# messages that are currently in the "unsent" state.
|
|
23
|
+
def unsent_messages
|
|
24
|
+
messages.with_state(:unsent)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Composed messages that have already been sent. These consists of all
|
|
28
|
+
# messages that are currently in the "queued" or "sent" states.
|
|
29
|
+
def sent_messages
|
|
30
|
+
messages.with_states(:queued, :sent)
|
|
31
|
+
end
|
|
83
32
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
33
|
+
# Returns the most recent message of each thread
|
|
34
|
+
def last_received_message_per_thread
|
|
35
|
+
MessageRecipient.find_all_by_receiver_id(id, :order => 'id desc', :joins => :message, :conditions => 'message_recipients.hidden_at is null', :group => 'COALESCE(original_message_id,messages.id)')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def conversations
|
|
39
|
+
(messages + received_messages.map(&:message)).compact.uniq
|
|
40
|
+
end
|
|
87
41
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
42
|
+
def original_conversations
|
|
43
|
+
conversations.select{ |message| message.original_message_id == nil }
|
|
44
|
+
end
|
|
91
45
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
end
|
|
46
|
+
def find_conversation_by_id(id)
|
|
47
|
+
conversations.select{ |message| message.id == id.to_i }.first
|
|
95
48
|
end
|
|
96
|
-
end
|
|
97
49
|
|
|
98
|
-
|
|
99
|
-
|
|
50
|
+
def unread_messages
|
|
51
|
+
received_messages.select(&:unread?).map(&:message)
|
|
52
|
+
end
|
|
100
53
|
end
|
|
101
54
|
|
|
102
55
|
require 'has_messages/models/message.rb'
|
|
@@ -31,7 +31,7 @@ class MessageRecipient < ActiveRecord::Base
|
|
|
31
31
|
|
|
32
32
|
validates_presence_of :message_id, :kind, :state, :receiver_id, :receiver_type
|
|
33
33
|
|
|
34
|
-
attr_protected :state, :position, :hidden_at
|
|
34
|
+
# attr_protected :state, :position, :hidden_at
|
|
35
35
|
|
|
36
36
|
before_create :set_position
|
|
37
37
|
before_destroy :reorder_positions
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'has_messages.rb'
|
metadata
CHANGED
|
@@ -1,47 +1,40 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: has_messages_huacnlee
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
prerelease:
|
|
6
|
-
segments:
|
|
7
|
-
- 0
|
|
8
|
-
- 4
|
|
9
|
-
- 1
|
|
10
|
-
version: 0.4.1
|
|
11
6
|
platform: ruby
|
|
12
|
-
authors:
|
|
7
|
+
authors:
|
|
13
8
|
- Aaron Pfeifer
|
|
9
|
+
- Jason Lee
|
|
14
10
|
autorequire:
|
|
15
11
|
bindir: bin
|
|
16
12
|
cert_chain: []
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
+
date: 2010-03-07 00:00:00.000000000 Z
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
21
16
|
name: state_machine
|
|
22
17
|
prerelease: false
|
|
23
|
-
requirement:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- !ruby/object:Gem::Version
|
|
28
|
-
hash: 3
|
|
29
|
-
segments:
|
|
30
|
-
- 0
|
|
31
|
-
- 7
|
|
32
|
-
- 0
|
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
|
19
|
+
requirements:
|
|
20
|
+
- - ! '>='
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
33
22
|
version: 0.7.0
|
|
23
|
+
none: false
|
|
34
24
|
type: :runtime
|
|
35
|
-
version_requirements:
|
|
36
|
-
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 0.7.0
|
|
30
|
+
none: false
|
|
31
|
+
description: has_messages fork for Rails 3, Demonstrates a reference implementation
|
|
32
|
+
for sending messages between users in ActiveRecord
|
|
37
33
|
email: aaron@pluginaweek.org
|
|
38
34
|
executables: []
|
|
39
|
-
|
|
40
35
|
extensions: []
|
|
41
|
-
|
|
42
36
|
extra_rdoc_files: []
|
|
43
|
-
|
|
44
|
-
files:
|
|
37
|
+
files:
|
|
45
38
|
- lib/generators/has_messages/has_messages_generator.rb
|
|
46
39
|
- lib/generators/has_messages/templates/001_create_messages.rb
|
|
47
40
|
- lib/generators/has_messages/templates/002_create_message_recipients.rb
|
|
@@ -49,57 +42,32 @@ files:
|
|
|
49
42
|
- lib/has_messages/models/message.rb
|
|
50
43
|
- lib/has_messages/models/message_recipient.rb
|
|
51
44
|
- lib/has_messages.rb
|
|
45
|
+
- lib/has_messages_huacnlee.rb
|
|
52
46
|
- init.rb
|
|
53
|
-
- README.
|
|
54
|
-
|
|
55
|
-
- test/app_root/config/environment.rb
|
|
56
|
-
- test/app_root/db/migrate/001_create_users.rb
|
|
57
|
-
- test/app_root/db/migrate/002_migrate_has_messages_to_version_2.rb
|
|
58
|
-
- test/factory.rb
|
|
59
|
-
- test/functional/has_messages_test.rb
|
|
60
|
-
- test/test_helper.rb
|
|
61
|
-
- test/unit/message_recipient_test.rb
|
|
62
|
-
- test/unit/message_test.rb
|
|
63
|
-
homepage: http://www.pluginaweek.org
|
|
47
|
+
- README.md
|
|
48
|
+
homepage: https://github.com/huacnlee/has_messages
|
|
64
49
|
licenses: []
|
|
65
|
-
|
|
66
50
|
post_install_message:
|
|
67
51
|
rdoc_options: []
|
|
68
|
-
|
|
69
|
-
require_paths:
|
|
52
|
+
require_paths:
|
|
70
53
|
- lib
|
|
71
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ! '>='
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
72
59
|
none: false
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- 0
|
|
79
|
-
version: "0"
|
|
80
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ! '>='
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '0'
|
|
81
65
|
none: false
|
|
82
|
-
requirements:
|
|
83
|
-
- - ">="
|
|
84
|
-
- !ruby/object:Gem::Version
|
|
85
|
-
hash: 3
|
|
86
|
-
segments:
|
|
87
|
-
- 0
|
|
88
|
-
version: "0"
|
|
89
66
|
requirements: []
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
rubygems_version: 1.8.8
|
|
67
|
+
rubyforge_project:
|
|
68
|
+
rubygems_version: 1.8.23
|
|
93
69
|
signing_key:
|
|
94
70
|
specification_version: 3
|
|
95
|
-
summary: Demonstrates a reference implementation for sending messages between users
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- test/app_root/config/environment.rb
|
|
99
|
-
- test/app_root/db/migrate/001_create_users.rb
|
|
100
|
-
- test/app_root/db/migrate/002_migrate_has_messages_to_version_2.rb
|
|
101
|
-
- test/factory.rb
|
|
102
|
-
- test/functional/has_messages_test.rb
|
|
103
|
-
- test/test_helper.rb
|
|
104
|
-
- test/unit/message_recipient_test.rb
|
|
105
|
-
- test/unit/message_test.rb
|
|
71
|
+
summary: Demonstrates a reference implementation for sending messages between users
|
|
72
|
+
in ActiveRecord
|
|
73
|
+
test_files: []
|