acts-as-messageable 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +11 -0
- data/README.rdoc +22 -64
- data/Rakefile +41 -19
- data/VERSION +1 -1
- data/acts-as-messageable.gemspec +67 -0
- data/lib/acts-as-messageable.rb +7 -7
- data/lib/acts-as-messageable/acts-as-messageable.rb +74 -0
- data/lib/acts-as-messageable/message.rb +74 -0
- data/lib/acts-as-messageable/relation.rb +12 -0
- data/lib/generators/{acts_as_messageable → acts-as-messageable}/migration/migration_generator.rb +5 -10
- data/lib/generators/{acts_as_messageable → acts-as-messageable}/migration/templates/migration.rb +4 -4
- data/rails/init.rb +1 -1
- data/spec/acts-as-messageable_spec.rb +61 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/user.rb +3 -0
- metadata +99 -44
- data/lib/acts_as_messageable/acts-as-messageable.rb +0 -94
- data/lib/acts_as_messageable/message.rb +0 -59
- data/test/message_test.rb +0 -114
data/Gemfile
ADDED
data/README.rdoc
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
= ActsAsMessageable
|
2
3
|
The Acts As Messageable allows communication between the models.
|
3
4
|
|
@@ -8,87 +9,44 @@ To use it, add it to your Gemfile:
|
|
8
9
|
|
9
10
|
== Post instalation
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
rails g acts_as_messageable:migration [table_name] # default 'messages'
|
13
|
+
rake db:migrate
|
13
14
|
|
14
15
|
== Usage
|
15
16
|
|
16
17
|
class User < ActiveRecord::Base
|
17
|
-
acts_as_messageable
|
18
|
+
acts_as_messageable :table_name => "table_with_messages", # default 'messages'
|
19
|
+
:required => :body # default [:topic, :body]
|
18
20
|
end
|
19
21
|
|
20
22
|
== Send message
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
@user1.send_message(@user2, "Message to user2", "Hi user 2!;-)")
|
25
|
-
@user2.send_message(@user1, "Re: Message to user2", "Hi there!:)")
|
26
|
-
|
27
|
-
== Inbox/Outbox
|
28
|
-
|
29
|
-
# Show inbox
|
30
|
-
@user.received
|
31
|
-
# Show inbox trash
|
32
|
-
@user.received(:deleted => true)
|
33
|
-
# Show inbox with inbox trash
|
34
|
-
@user.received(:all => true)
|
35
|
-
|
36
|
-
# Show outbox
|
37
|
-
@user.sent
|
38
|
-
# Show outbox trash
|
39
|
-
@user.sent(:deleted => true)
|
40
|
-
# Show outbox with inbox trash
|
41
|
-
@user.sent(:all => true)
|
42
|
-
|
43
|
-
# Show trash
|
44
|
-
@user.messages(:deleted => true)
|
45
|
-
# Show all messages
|
46
|
-
@user.messages(:all => true)
|
24
|
+
@alice = User.first
|
25
|
+
@bob = User.last
|
47
26
|
|
48
|
-
|
27
|
+
@alice.send_message(@bob, "Message topic", "Hi bob!")
|
28
|
+
@bob.send_message(@alice, "Re: Message topic", "Hi alice!")
|
49
29
|
|
50
|
-
|
51
|
-
@
|
52
|
-
|
53
|
-
end
|
30
|
+
== New API
|
31
|
+
@alice.messages -- all messages connected with @alice (inbox/outbox)
|
32
|
+
@alice.deleted_messages -- all messages connected with @alice (trash)
|
54
33
|
|
55
|
-
@
|
56
|
-
|
57
|
-
|
34
|
+
@alice.messages.are_from(@bob) -- all message form @bob
|
35
|
+
@alice.messages.are_to(@bob) -- all message to @bob
|
36
|
+
@alice.messages.id(@id_of_message) -- message with id id_of_message
|
37
|
+
@alice.messages.readed -- all readed @alice messages
|
38
|
+
@alice.messages.unaded -- all unreaded @alice messages
|
58
39
|
|
59
|
-
|
60
|
-
message.delete
|
61
|
-
end
|
40
|
+
You can use multiple filters at the same time
|
62
41
|
|
63
|
-
@
|
64
|
-
|
65
|
-
end
|
42
|
+
@alice.messages.are_from(@bob).are_to(@alice).readed -- all message from @bob to @alice and readed
|
43
|
+
@alice.deleted_message.are_from(@bob) -- all deleted messages from @bob
|
66
44
|
|
67
|
-
|
68
|
-
messsage.delete
|
69
|
-
end
|
45
|
+
=== Delete message
|
70
46
|
|
71
|
-
@
|
47
|
+
@alice.messages.process do |message|
|
72
48
|
message.delete
|
73
49
|
end
|
74
50
|
|
75
51
|
|
76
|
-
# Delete by hand
|
77
|
-
@user.delete_message(@user.messages(:id => 10))
|
78
|
-
|
79
|
-
== Search
|
80
|
-
|
81
|
-
# Search message
|
82
|
-
@user.messages # all messages (in and out)
|
83
|
-
@user.messages(:from => @user2) # all messages from @user2
|
84
|
-
@user.messages(:to => @user2) # all messages to @user2
|
85
|
-
@user.messages(:id => 2) # message where message.id = 2
|
86
|
-
|
87
|
-
== Blocks time ;-)
|
88
|
-
|
89
|
-
@user.messages do |messsage|
|
90
|
-
# message stuff...
|
91
|
-
end
|
92
|
-
|
93
52
|
Copyright © 2011 Piotr Niełacny (http://ruby-blog.pl), released under the MIT license
|
94
|
-
|
data/Rakefile
CHANGED
@@ -1,24 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
1
12
|
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
13
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
gem.name = "acts-as-messageable"
|
17
|
+
gem.email = "piotr.nielacny@gmail.com"
|
18
|
+
gem.summary = "Make user messageable!;-)"
|
19
|
+
gem.homepage = "http://github.com/LTe/acts_as_messageable"
|
20
|
+
gem.authors = ["Piotr Nielacny"]
|
21
|
+
# dependencies defined in Gemfile
|
9
22
|
end
|
23
|
+
Jeweler::RubygemsDotOrgTasks.new
|
10
24
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
require 'rspec/core'
|
26
|
+
require 'rspec/core/rake_task'
|
27
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
28
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "acts-as-messageable #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
46
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{acts-as-messageable}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Piotr Nielacny"]
|
12
|
+
s.date = %q{2011-05-04}
|
13
|
+
s.email = %q{piotr.nielacny@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.rdoc"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
"Gemfile",
|
19
|
+
"MIT-LICENSE",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"acts-as-messageable.gemspec",
|
24
|
+
"lib/acts-as-messageable.rb",
|
25
|
+
"lib/acts-as-messageable/acts-as-messageable.rb",
|
26
|
+
"lib/acts-as-messageable/message.rb",
|
27
|
+
"lib/acts-as-messageable/relation.rb",
|
28
|
+
"lib/generators/acts-as-messageable/migration/migration_generator.rb",
|
29
|
+
"lib/generators/acts-as-messageable/migration/templates/migration.rb",
|
30
|
+
"rails/init.rb",
|
31
|
+
"spec/acts-as-messageable_spec.rb",
|
32
|
+
"spec/spec_helper.rb",
|
33
|
+
"spec/support/user.rb"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/LTe/acts_as_messageable}
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.6.2}
|
38
|
+
s.summary = %q{Make user messageable!;-)}
|
39
|
+
|
40
|
+
if s.respond_to? :specification_version then
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0.0"])
|
45
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
46
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
47
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
|
48
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
49
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
52
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
53
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
54
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
|
55
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
56
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
60
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
61
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
|
63
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
64
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/acts-as-messageable.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require "active_record"
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require 'acts_as_messageable/acts-as-messageable'
|
6
|
-
require 'acts_as_messageable/message'
|
7
|
-
|
8
|
-
$LOAD_PATH.shift
|
2
|
+
require 'acts-as-messageable/acts-as-messageable'
|
3
|
+
require 'acts-as-messageable/message'
|
4
|
+
require 'acts-as-messageable/relation'
|
9
5
|
|
10
6
|
if defined?(ActiveRecord::Base)
|
11
7
|
ActiveRecord::Base.send :include, ActsAsMessageable::Model
|
12
8
|
end
|
9
|
+
|
10
|
+
if defined?(ActiveRecord::Relation)
|
11
|
+
ActiveRecord::Relation.send :include, ActsAsMessageable::Relation
|
12
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module ActsAsMessageable
|
2
|
+
module Model
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Method make ActiveRecord::Base object messageable
|
10
|
+
# @param [Symbol] :table_name - table name for messages
|
11
|
+
def acts_as_messageable(options = {})
|
12
|
+
class_eval do
|
13
|
+
has_many :received_messages,
|
14
|
+
:as => :received_messageable,
|
15
|
+
:class_name => "ActsAsMessageable::Message",
|
16
|
+
:dependent => :nullify
|
17
|
+
has_many :sent_messages,
|
18
|
+
:as => :sent_messageable,
|
19
|
+
:class_name => "ActsAsMessageable::Message",
|
20
|
+
:dependent => :nullify
|
21
|
+
end
|
22
|
+
|
23
|
+
table_name = %q{set_table_name "#{options[:table_name] || "messages"}"}
|
24
|
+
ActsAsMessageable::Message.class_eval(table_name)
|
25
|
+
|
26
|
+
validation = %q{validates_presence_of options[:required] || [:topic ,:body]}
|
27
|
+
ActsAsMessageable::Message.class_eval(validation)
|
28
|
+
|
29
|
+
include ActsAsMessageable::Model::InstanceMethods
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
module InstanceMethods
|
35
|
+
# Get all messages connected with user
|
36
|
+
# @return [ActiveRecord::Relation] all messages connected with user
|
37
|
+
def messages(trash = false)
|
38
|
+
result = ActsAsMessageable::Message.connected_with(self, trash)
|
39
|
+
result.relation_context = self
|
40
|
+
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def deleted_messages
|
45
|
+
messages true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Method sens message to another user
|
49
|
+
# @param [ActiveRecord::Base] to
|
50
|
+
# @param [String] topic
|
51
|
+
# @param [String] body
|
52
|
+
#
|
53
|
+
# @return [ActsAsMessageable::Message] the message object
|
54
|
+
def send_message(to, topic, body)
|
55
|
+
@message = ActsAsMessageable::Message.create!(:topic => topic, :body => body)
|
56
|
+
|
57
|
+
self.sent_messages << @message
|
58
|
+
to.received_messages << @message
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete_message(message)
|
62
|
+
current_user = self
|
63
|
+
|
64
|
+
if message.received_messageable == current_user
|
65
|
+
message.update_attributes!(:recipient_delete => true)
|
66
|
+
elsif message.sent_messageable == current_user
|
67
|
+
message.update_attributes!(:sender_delete => true)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module ActsAsMessageable
|
2
|
+
class Message < ::ActiveRecord::Base
|
3
|
+
belongs_to :received_messageable, :polymorphic => true
|
4
|
+
belongs_to :sent_messageable, :polymorphic => true
|
5
|
+
|
6
|
+
attr_accessible :topic,
|
7
|
+
:body,
|
8
|
+
:received_messageable_type,
|
9
|
+
:received_messageable_id,
|
10
|
+
:sent_messageable_type,
|
11
|
+
:sent_messageable_id,
|
12
|
+
:opened,
|
13
|
+
:recipient_delete,
|
14
|
+
:sender_delete
|
15
|
+
|
16
|
+
attr_accessor :context, :removed
|
17
|
+
|
18
|
+
# Sample documentation for scope
|
19
|
+
scope :are_from, lambda { |*args| where("sent_messageable_id = :sender", :sender => args.first) }
|
20
|
+
scope :are_to, lambda { |*args| where("received_messageable_id = :receiver", :receiver => args.first) }
|
21
|
+
scope :id, lambda { |*args| where("id = :id", :id => args.first) }
|
22
|
+
|
23
|
+
scope :connected_with, lambda { |*args| where("(sent_messageable_type = :sent_type and
|
24
|
+
sent_messageable_id = :sent_id and
|
25
|
+
sender_delete = :s_delete) or
|
26
|
+
(received_messageable_type = :received_type and
|
27
|
+
received_messageable_id = :received_id and
|
28
|
+
recipient_delete = :r_delete)",
|
29
|
+
:sent_type => args.first.class.name,
|
30
|
+
:sent_id => args.first.id,
|
31
|
+
:received_type => args.first.class.name,
|
32
|
+
:received_id => args.first.id,
|
33
|
+
:r_delete => args.last,
|
34
|
+
:s_delete => args.last)
|
35
|
+
}
|
36
|
+
scope :readed, lambda { where("opened = :opened", :opened => true) }
|
37
|
+
scope :unread, lambda { where("opened = :opened", :opened => false) }
|
38
|
+
scope :deleted, lambda { where("recipient_delete = :r_delete AND sender_delete = :s_delete",
|
39
|
+
:r_delete => true, :s_delete => true)}
|
40
|
+
|
41
|
+
def open?
|
42
|
+
self.opened?
|
43
|
+
end
|
44
|
+
|
45
|
+
def open
|
46
|
+
update_attributes!(:opened => true)
|
47
|
+
end
|
48
|
+
|
49
|
+
def mark_as_read
|
50
|
+
open
|
51
|
+
end
|
52
|
+
|
53
|
+
def close
|
54
|
+
update_attributes!(:opened => false)
|
55
|
+
end
|
56
|
+
|
57
|
+
def mark_as_unread
|
58
|
+
close
|
59
|
+
end
|
60
|
+
|
61
|
+
def from
|
62
|
+
sent_messageable
|
63
|
+
end
|
64
|
+
|
65
|
+
def to
|
66
|
+
received_messageable
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete
|
70
|
+
self.removed = true
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ActsAsMessageable
|
2
|
+
module Relation
|
3
|
+
attr_accessor :relation_context
|
4
|
+
|
5
|
+
def process(context = self.relation_context, &block)
|
6
|
+
self.each do |message|
|
7
|
+
block.call(message) if block_given?
|
8
|
+
context.delete_message(message) if message.removed
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/generators/{acts_as_messageable → acts-as-messageable}/migration/migration_generator.rb
RENAMED
@@ -1,25 +1,20 @@
|
|
1
1
|
require 'rails/generators/migration'
|
2
|
+
require 'rails/generators/active_record'
|
2
3
|
|
3
4
|
module ActsAsMessageable
|
4
5
|
class MigrationGenerator < Rails::Generators::Base
|
5
6
|
include Rails::Generators::Migration
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
8
|
+
source_root File.join(File.dirname(__FILE__), 'templates')
|
9
|
+
argument :table_name, :type => :string, :default => "messages"
|
10
10
|
|
11
11
|
def self.next_migration_number(dirname)
|
12
|
-
|
13
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
14
|
-
else
|
15
|
-
"%.3d" % (current_migration_number(dirname) + 1)
|
16
|
-
end
|
12
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
17
13
|
end
|
18
14
|
|
19
15
|
def create_migration_file
|
20
16
|
migration_template 'migration.rb', 'db/migrate/create_messages_table.rb'
|
21
17
|
end
|
22
18
|
|
23
|
-
|
24
19
|
end
|
25
|
-
end
|
20
|
+
end
|
data/lib/generators/{acts_as_messageable → acts-as-messageable}/migration/templates/migration.rb
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
class CreateMessagesTable < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
|
-
create_table
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
4
|
t.string :topic
|
5
5
|
t.text :body
|
6
6
|
t.references :received_messageable, :polymorphic => true
|
@@ -11,10 +11,10 @@ class CreateMessagesTable < ActiveRecord::Migration
|
|
11
11
|
t.boolean :sender_delete, :default => false
|
12
12
|
end
|
13
13
|
|
14
|
-
add_index
|
14
|
+
add_index :<%= table_name %>, [:sent_messageable_id, :received_messageable_id], :name => "acts_as_messageable_ids"
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.down
|
18
|
-
drop_table
|
18
|
+
drop_table :<%= table_name %>
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
data/rails/init.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require 'acts-as-messageable'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "ActsAsMessageable" do
|
4
|
+
it "should be two users in database" do
|
5
|
+
User.count.should == 2
|
6
|
+
end
|
7
|
+
|
8
|
+
it "alice should have one message from bob" do
|
9
|
+
@bob.send_message(@alice, "Topic", "Message body")
|
10
|
+
@alice.messages.count.should == 1
|
11
|
+
@alice.messages.are_from(@bob).count.should == 1
|
12
|
+
end
|
13
|
+
|
14
|
+
it "bob should have one message to alice in outbox" do
|
15
|
+
@bob.send_message(@alice, "Topic", "Message body")
|
16
|
+
@bob.messages.count.should == 1
|
17
|
+
@bob.messages.are_to(@alice).count.should == 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it "bob should have one open message from alice" do
|
21
|
+
@alice.send_message(@bob, "Topic", "Message body")
|
22
|
+
@bob.messages.are_from(@alice).process do |m|
|
23
|
+
m.open
|
24
|
+
end
|
25
|
+
|
26
|
+
@bob.messages.readed.count.should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it "bob should have one deleted message from alice" do
|
30
|
+
@alice.send_message(@bob, "Topic", "Message body")
|
31
|
+
@bob.messages.process do |m|
|
32
|
+
m.delete
|
33
|
+
end
|
34
|
+
|
35
|
+
@bob.messages.each do |m|
|
36
|
+
m.recipient_delete.should == true
|
37
|
+
m.sender_delete.should == false
|
38
|
+
end
|
39
|
+
|
40
|
+
@bob.deleted_messages.count.should == 1
|
41
|
+
@bob.messages.count.should == 0
|
42
|
+
end
|
43
|
+
|
44
|
+
it "alice should have one unread message from bob" do
|
45
|
+
@bob.send_message(@alice, "Topic", "Message body")
|
46
|
+
@alice.messages.are_from(@bob).unread.count.should == 1
|
47
|
+
@alice.messages.are_from(@bob).readed.count.should == 0
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be in database message with id ..." do
|
51
|
+
message_id = @bob.send_message(@alice, "Topic", "Message body").first.id
|
52
|
+
@bob.messages.id(message_id).count.should == 1
|
53
|
+
end
|
54
|
+
|
55
|
+
it "message should have proper topic" do
|
56
|
+
@bob.send_message(@alice, "Topic", "Message body")
|
57
|
+
@bob.messages.count.should == 1
|
58
|
+
@bob.messages.first.topic == "Topic"
|
59
|
+
@bob.messages.first.body == "Message body"
|
60
|
+
end
|
61
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'acts-as-messageable'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.before(:all) do
|
12
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
13
|
+
create_database
|
14
|
+
|
15
|
+
@alice = User.create :email => "alice@example.com"
|
16
|
+
@bob = User.create :email => "bob@example.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
config.after(:all) do
|
20
|
+
drop_database
|
21
|
+
end
|
22
|
+
|
23
|
+
config.after(:each) do
|
24
|
+
ActsAsMessageable::Message.destroy_all
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_database
|
29
|
+
ActiveRecord::Schema.define(:version => 1) do
|
30
|
+
create_table :messages do |t|
|
31
|
+
t.string :topic
|
32
|
+
t.text :body
|
33
|
+
t.references :received_messageable, :polymorphic => true
|
34
|
+
t.references :sent_messageable, :polymorphic => true
|
35
|
+
t.boolean :opened, :default => false
|
36
|
+
t.boolean :opened, :default => false
|
37
|
+
t.boolean :recipient_delete, :default => false
|
38
|
+
t.boolean :sender_delete, :default => false
|
39
|
+
end
|
40
|
+
|
41
|
+
create_table :users do |t|
|
42
|
+
t.string :email
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def drop_database
|
48
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
49
|
+
ActiveRecord::Base.connection.drop_table(table)
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,77 +1,132 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts-as-messageable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Piotr Nielacny
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-02-17 00:00:00 +01:00
|
12
|
+
date: 2011-05-04 00:00:00.000000000 +02:00
|
19
13
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
requirement: &21323640 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *21323640
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: &21321880 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *21321880
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
requirement: &21318760 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.0.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *21318760
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: jeweler
|
50
|
+
requirement: &21317420 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.6.0
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *21317420
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rcov
|
61
|
+
requirement: &21316360 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *21316360
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: sqlite3-ruby
|
72
|
+
requirement: &21314120 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *21314120
|
22
81
|
description:
|
23
82
|
email: piotr.nielacny@gmail.com
|
24
83
|
executables: []
|
25
|
-
|
26
84
|
extensions: []
|
27
|
-
|
28
|
-
extra_rdoc_files:
|
85
|
+
extra_rdoc_files:
|
29
86
|
- README.rdoc
|
30
|
-
files:
|
87
|
+
files:
|
88
|
+
- Gemfile
|
31
89
|
- MIT-LICENSE
|
32
90
|
- README.rdoc
|
33
91
|
- Rakefile
|
34
92
|
- VERSION
|
93
|
+
- acts-as-messageable.gemspec
|
35
94
|
- lib/acts-as-messageable.rb
|
36
|
-
- lib/
|
37
|
-
- lib/
|
38
|
-
- lib/
|
39
|
-
- lib/generators/
|
95
|
+
- lib/acts-as-messageable/acts-as-messageable.rb
|
96
|
+
- lib/acts-as-messageable/message.rb
|
97
|
+
- lib/acts-as-messageable/relation.rb
|
98
|
+
- lib/generators/acts-as-messageable/migration/migration_generator.rb
|
99
|
+
- lib/generators/acts-as-messageable/migration/templates/migration.rb
|
40
100
|
- rails/init.rb
|
41
|
-
-
|
101
|
+
- spec/acts-as-messageable_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
- spec/support/user.rb
|
42
104
|
has_rdoc: true
|
43
105
|
homepage: http://github.com/LTe/acts_as_messageable
|
44
106
|
licenses: []
|
45
|
-
|
46
107
|
post_install_message:
|
47
108
|
rdoc_options: []
|
48
|
-
|
49
|
-
require_paths:
|
109
|
+
require_paths:
|
50
110
|
- lib
|
51
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
112
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
|
57
|
-
segments:
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
segments:
|
58
118
|
- 0
|
59
|
-
|
60
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
hash: 4567414755196272734
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
121
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
66
|
-
segments:
|
67
|
-
- 0
|
68
|
-
version: "0"
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
69
126
|
requirements: []
|
70
|
-
|
71
127
|
rubyforge_project:
|
72
|
-
rubygems_version: 1.
|
128
|
+
rubygems_version: 1.6.2
|
73
129
|
signing_key:
|
74
130
|
specification_version: 3
|
75
131
|
summary: Make user messageable!;-)
|
76
|
-
test_files:
|
77
|
-
- test/message_test.rb
|
132
|
+
test_files: []
|
@@ -1,94 +0,0 @@
|
|
1
|
-
module ActsAsMessageable
|
2
|
-
module Model
|
3
|
-
|
4
|
-
def self.included(base)
|
5
|
-
base.extend ClassMethods
|
6
|
-
end
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
def acts_as_messageable
|
10
|
-
class_eval do
|
11
|
-
has_many :received_messages, :as => :received_messageable, :class_name => "ActsAsMessageable::Message"
|
12
|
-
has_many :sent_messages, :as => :sent_messageable, :class_name => "ActsAsMessageable::Message"
|
13
|
-
end
|
14
|
-
|
15
|
-
include ActsAsMessageable::Model::InstanceMethods
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
module InstanceMethods
|
21
|
-
def messages(options = {}, &block)
|
22
|
-
result = options.blank? ? (self.received + self.sent) : ActsAsMessageable::Message.scoped
|
23
|
-
filter(result, options, &block)
|
24
|
-
end
|
25
|
-
|
26
|
-
def received(options = {}, &block)
|
27
|
-
if options[:all]
|
28
|
-
result = self.received_messages
|
29
|
-
elsif options[:deleted]
|
30
|
-
result = self.received_messages.where(:recipient_delete => true)
|
31
|
-
else
|
32
|
-
result = self.received_messages.where(:recipient_delete => false)
|
33
|
-
end
|
34
|
-
|
35
|
-
filter(result, options, &block)
|
36
|
-
end
|
37
|
-
|
38
|
-
def sent(options = {}, &block)
|
39
|
-
if options[:all]
|
40
|
-
result = self.sent_messages
|
41
|
-
elsif options[:deleted]
|
42
|
-
result = self.sent_messages.where(:sender_delete => true)
|
43
|
-
else
|
44
|
-
result = self.sent_messages.where(:sender_delete => false)
|
45
|
-
end
|
46
|
-
|
47
|
-
filter(result, options, &block)
|
48
|
-
end
|
49
|
-
|
50
|
-
def send_message(to, topic, body)
|
51
|
-
@message = ActsAsMessageable::Message.create!(:topic => topic, :body => body)
|
52
|
-
|
53
|
-
self.sent_messages << @message
|
54
|
-
to.received_messages << @message
|
55
|
-
end
|
56
|
-
|
57
|
-
def delete_message(message)
|
58
|
-
current_user = self
|
59
|
-
|
60
|
-
if message.received_messageable == current_user
|
61
|
-
message.update_attributes!(:recipient_delete => true)
|
62
|
-
elsif message.sent_messageable == current_user
|
63
|
-
message.update_attributes!(:sender_delete => true)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def filter(result, options = {}, &block)
|
70
|
-
current_user = self
|
71
|
-
|
72
|
-
options.each do |key, value|
|
73
|
-
case key
|
74
|
-
when :from then
|
75
|
-
result = result.messages_from(value, current_user)
|
76
|
-
when :to then
|
77
|
-
result = result.messages_to(value, current_user)
|
78
|
-
when :id then
|
79
|
-
result = result.message_id(value)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
result.each do |message|
|
84
|
-
block.call(message)
|
85
|
-
delete_message(message) if message.delete_message
|
86
|
-
end if block_given?
|
87
|
-
|
88
|
-
result
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module ActsAsMessageable
|
2
|
-
class Message < ::ActiveRecord::Base
|
3
|
-
belongs_to :received_messageable, :polymorphic => true
|
4
|
-
belongs_to :sent_messageable, :polymorphic => true
|
5
|
-
|
6
|
-
attr_accessible :topic,
|
7
|
-
:body,
|
8
|
-
:received_messageable_type,
|
9
|
-
:received_messageable_id,
|
10
|
-
:sent_messageable_type,
|
11
|
-
:sent_messageable_id,
|
12
|
-
:opened,
|
13
|
-
:recipient_delete,
|
14
|
-
:sender_delete
|
15
|
-
|
16
|
-
attr_accessor :delete_message
|
17
|
-
|
18
|
-
scope :messages_from, lambda { |*args| where("sent_messageable_id = :sender", :sender => args.first).
|
19
|
-
where("received_messageable_id = :receiver", :receiver => args.last) }
|
20
|
-
scope :messages_to, lambda { |*args| where("received_messageable_id = :receiver", :receiver => args.first).
|
21
|
-
where("sent_messageable_id = :sender", :sender => args.last)}
|
22
|
-
scope :message_id, lambda { |*args| where("id = :id", :id => args.first) }
|
23
|
-
|
24
|
-
validates_presence_of :topic ,:body
|
25
|
-
|
26
|
-
def open?
|
27
|
-
self.opened?
|
28
|
-
end
|
29
|
-
|
30
|
-
def open
|
31
|
-
update_attributes!(:opened => true)
|
32
|
-
end
|
33
|
-
|
34
|
-
def mark_as_read
|
35
|
-
open
|
36
|
-
end
|
37
|
-
|
38
|
-
def close
|
39
|
-
update_attributes!(:opened => false)
|
40
|
-
end
|
41
|
-
|
42
|
-
def mark_as_unread
|
43
|
-
close
|
44
|
-
end
|
45
|
-
|
46
|
-
def from
|
47
|
-
"#{self.sent_messageable_type}".constantize.find(self.sent_messageable_id)
|
48
|
-
end
|
49
|
-
|
50
|
-
def to
|
51
|
-
"#{self.received_messageable_type}".constantize.find(self.received_messageable_id)
|
52
|
-
end
|
53
|
-
|
54
|
-
def delete
|
55
|
-
self.delete_message = true
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
data/test/message_test.rb
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require "rubygems"
|
3
|
-
|
4
|
-
require File.expand_path('../../lib/acts-as-messageable.rb', __FILE__)
|
5
|
-
|
6
|
-
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
7
|
-
|
8
|
-
def create_db
|
9
|
-
ActiveRecord::Schema.define(:version => 1) do
|
10
|
-
create_table :messages do |t|
|
11
|
-
t.string :topic
|
12
|
-
t.text :body
|
13
|
-
t.references :received_messageable, :polymorphic => true
|
14
|
-
t.references :sent_messageable, :polymorphic => true
|
15
|
-
t.boolean :opened, :default => false
|
16
|
-
t.boolean :opened, :default => false
|
17
|
-
t.boolean :recipient_delete, :default => false
|
18
|
-
t.boolean :sender_delete, :default => false
|
19
|
-
end
|
20
|
-
|
21
|
-
create_table :users do |t|
|
22
|
-
t.string :email
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def drop_db
|
30
|
-
ActiveRecord::Base.connection.tables.each do |table|
|
31
|
-
ActiveRecord::Base.connection.drop_table(table)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class User < ActiveRecord::Base
|
36
|
-
acts_as_messageable
|
37
|
-
end
|
38
|
-
|
39
|
-
class MessageTest < Test::Unit::TestCase
|
40
|
-
def setup
|
41
|
-
create_db
|
42
|
-
User.create!(:email => "user1@users.com")
|
43
|
-
User.create!(:email => "user2@users.com")
|
44
|
-
end
|
45
|
-
|
46
|
-
def teardown
|
47
|
-
drop_db
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_send_message
|
51
|
-
u1 = User.first
|
52
|
-
u2 = User.last
|
53
|
-
|
54
|
-
u1.send_message(u2, "Topic", "Body")
|
55
|
-
u2.send_message(u1, "Topic2", "Body2")
|
56
|
-
|
57
|
-
assert_equal ["Topic", "Topic2"], ActsAsMessageable::Message.find(:all).map(&:topic)
|
58
|
-
assert_equal ["Body", "Body2"], ActsAsMessageable::Message.find(:all).map(&:body)
|
59
|
-
assert_equal u1.id, ActsAsMessageable::Message.find(:first, :conditions => { :topic => "Topic" }).sent_messageable_id
|
60
|
-
assert_equal u2.id, ActsAsMessageable::Message.find(:first, :conditions => { :topic => "Topic" }).received_messageable_id
|
61
|
-
|
62
|
-
assert_equal u2.id, ActsAsMessageable::Message.find(:first, :conditions => { :topic => "Topic2" }).sent_messageable_id
|
63
|
-
assert_equal u1.id, ActsAsMessageable::Message.find(:first, :conditions => { :topic => "Topic2" }).received_messageable_id
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_received
|
67
|
-
u1 = User.first
|
68
|
-
u2 = User.last
|
69
|
-
|
70
|
-
u1.send_message(u2, "Topic", "Body")
|
71
|
-
u1.send_message(u2, "Topic2", "Body2")
|
72
|
-
|
73
|
-
assert_equal ["Topic", "Topic2"], u2.received.map(&:topic)
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_sent
|
77
|
-
u1 = User.first
|
78
|
-
u2 = User.last
|
79
|
-
|
80
|
-
u1.send_message(u2, "Topic", "Body")
|
81
|
-
u1.send_message(u2, "Topic2", "Body2")
|
82
|
-
|
83
|
-
assert_equal ["Topic", "Topic2"], u1.sent.map(&:topic)
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_messages
|
87
|
-
u1 = User.first
|
88
|
-
u2 = User.last
|
89
|
-
|
90
|
-
u1.send_message(u2, "Topic", "Body")
|
91
|
-
u1.send_message(u2, "Topic2", "Body2")
|
92
|
-
|
93
|
-
assert_equal ["Topic", "Topic2"], u2.messages(:from => u1).map(&:topic)
|
94
|
-
assert_equal ["Topic", "Topic2"], u1.messages(:to => u2).map(&:topic)
|
95
|
-
assert_equal ["Topic"], u1.messages(:to => u2, :id => 1).map(&:topic)
|
96
|
-
assert_equal ["Topic2"], u1.messages(:id => 2).map(&:topic)
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_delete_message
|
100
|
-
u1 = User.first
|
101
|
-
u2 = User.last
|
102
|
-
|
103
|
-
u1.send_message(u2, "Topic", "Body")
|
104
|
-
u1.send_message(u2, "Topic2", "Body2")
|
105
|
-
|
106
|
-
u1.messages do |m|
|
107
|
-
m.delete
|
108
|
-
end
|
109
|
-
|
110
|
-
assert_equal [], u1.messages
|
111
|
-
assert_equal ["Topic", "Topic2"], u2.messages.map(&:topic)
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|