facteur 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/CHANGELOG +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +115 -0
- data/LICENSE +20 -20
- data/README.markdown +135 -137
- data/Rakefile +19 -41
- data/lib/facteur.rb +25 -14
- data/lib/facteur/active_record_addressee_model.rb +12 -0
- data/lib/facteur/active_record_mailbox_model.rb +15 -0
- data/lib/facteur/active_record_message_model.rb +24 -0
- data/lib/facteur/addressee_model.rb +29 -130
- data/lib/facteur/base_addressee_model.rb +163 -0
- data/lib/facteur/mailbox.rb +16 -0
- data/lib/facteur/mailbox_model.rb +9 -6
- data/lib/facteur/message.rb +16 -0
- data/lib/facteur/message_model.rb +16 -16
- data/lib/facteur/mongoid_addressee_model.rb +12 -0
- data/lib/facteur/mongoid_mailbox_model.rb +18 -0
- data/lib/facteur/mongoid_message_model.rb +19 -0
- data/lib/facteur/version.rb +3 -0
- data/lib/generators/facteur/install/install_generator.rb +25 -28
- data/lib/generators/facteur/install/templates/create_mailboxes.rb +14 -14
- data/lib/generators/facteur/install/templates/create_messages.rb +19 -19
- data/spec/activerecord/activerecord_spec_helper.rb +11 -0
- data/spec/activerecord/facteur_spec.rb +47 -0
- data/spec/mongoid/facteur_spec.rb +49 -0
- data/spec/mongoid/mongoid_spec_helper.rb +11 -0
- data/spec/spec_helper.rb +10 -67
- data/spec/support/activerecord/schema.rb +32 -0
- data/spec/{facteur_spec.rb → support/facteur_examples.rb} +38 -49
- data/spec/support/mongoid/database.rb +12 -0
- metadata +139 -20
- data/.document +0 -5
- data/VERSION +0 -1
- data/lib/facteur/rails/tasks/facteur.rake +0 -13
- data/lib/generators/facteur/install/templates/mailbox.rb +0 -3
- data/lib/generators/facteur/install/templates/message.rb +0 -3
data/Rakefile
CHANGED
@@ -1,41 +1,19 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
require 'rspec/core'
|
22
|
-
require 'rspec/core/rake_task'
|
23
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
24
|
-
end
|
25
|
-
|
26
|
-
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
27
|
-
end
|
28
|
-
|
29
|
-
task :spec => :check_dependencies
|
30
|
-
|
31
|
-
task :default => :spec
|
32
|
-
|
33
|
-
require 'rake/rdoctask'
|
34
|
-
Rake::RDocTask.new do |rdoc|
|
35
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
36
|
-
|
37
|
-
rdoc.rdoc_dir = 'rdoc'
|
38
|
-
rdoc.title = "facteur #{version}"
|
39
|
-
rdoc.rdoc_files.include('README*')
|
40
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
41
|
-
end
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
namespace :spec do
|
8
|
+
Rspec::Core::RakeTask.new(:activerecord) do |t|
|
9
|
+
t.pattern = "./spec/activerecord/**/*_spec.rb"
|
10
|
+
t.rspec_opts = "--format Fuubar"
|
11
|
+
end
|
12
|
+
|
13
|
+
Rspec::Core::RakeTask.new(:mongoid) do |t|
|
14
|
+
t.pattern = "./spec/mongoid/**/*_spec.rb"
|
15
|
+
t.rspec_opts = "--format Fuubar"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
data/lib/facteur.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/dependencies/autoload'
|
3
|
+
|
4
|
+
module Facteur
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :ActiveRecordMessageModel
|
8
|
+
autoload :MongoidMessageModel
|
9
|
+
autoload :MessageModel
|
10
|
+
autoload :ActiveRecordMailboxModel
|
11
|
+
autoload :MongoidMailboxModel
|
12
|
+
autoload :MailboxModel
|
13
|
+
autoload :BaseAddresseeModel
|
14
|
+
autoload :ActiveRecordAddresseeModel
|
15
|
+
autoload :MongoidAddresseeModel
|
16
|
+
autoload :AddresseeModel
|
17
|
+
|
18
|
+
def self.addressee_model
|
19
|
+
@addressee_model || "User"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.addressee_model=(model)
|
23
|
+
@addressee_model = model
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Facteur
|
4
|
+
module ActiveRecordAddresseeModel
|
5
|
+
include Facteur::BaseAddresseeModel
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_many :mailboxes, :as => :addressee, :class_name => "Facteur::Mailbox"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Facteur
|
4
|
+
module ActiveRecordMailboxModel
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
belongs_to :addressee, :polymorphic => true
|
9
|
+
has_many :messages, :class_name => "Facteur::Message"
|
10
|
+
|
11
|
+
validates_presence_of :name
|
12
|
+
validates_uniqueness_of :name, :scope => [:addressee_id, :addressee_type]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Facteur
|
4
|
+
module ActiveRecordMessageModel
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
validates_presence_of :author_id, :mailbox_id, :body
|
9
|
+
|
10
|
+
belongs_to :mailbox,
|
11
|
+
:class_name => "Facteur::Mailbox"
|
12
|
+
|
13
|
+
belongs_to :author,
|
14
|
+
:class_name => Facteur.addressee_model,
|
15
|
+
:foreign_key => "author_id"
|
16
|
+
|
17
|
+
has_and_belongs_to_many :addressees,
|
18
|
+
:class_name => Facteur.addressee_model,
|
19
|
+
:join_table => "messages_addressees",
|
20
|
+
:association_foreign_key => "addressee_id"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -1,145 +1,44 @@
|
|
1
1
|
module Facteur
|
2
2
|
module AddresseeModel
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
Facteur.addressee_model = self.to_s
|
7
|
+
Facteur.send(:remove_const, :Mailbox) if Facteur.const_defined?(:Mailbox)
|
8
|
+
Facteur.send(:remove_const, :Message) if Facteur.const_defined?(:Message)
|
9
|
+
|
10
|
+
if self.ancestors.map(&:to_s).include?("ActiveRecord::Base")
|
6
11
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# the addressee's mailboxes are created after its creation
|
11
|
-
after_create :create_mailboxes
|
12
|
-
end
|
13
|
-
|
14
|
-
receiver.extend ClassMethods
|
15
|
-
end
|
16
|
-
|
17
|
-
module ClassMethods
|
18
|
-
|
19
|
-
# Define a mailbox. The following options are available:
|
20
|
-
# <tt>:default</tt>:: defines the default mailbox. You must choose one default mailbox
|
21
|
-
def mailbox(name, options={})
|
22
|
-
mailbox = {:name => name}
|
23
|
-
mailbox.merge! options
|
24
|
-
mailboxes << mailbox
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns the mailboxes defined for the class
|
28
|
-
def mailboxes
|
29
|
-
@mailboxes ||= []
|
30
|
-
end
|
31
|
-
|
32
|
-
def update_addressees_mailboxes
|
33
|
-
all.each do |addressee|
|
34
|
-
@mailboxes.each do |mailbox|
|
35
|
-
options = {}.merge(mailbox)
|
36
|
-
name = options.delete(:name)
|
37
|
-
addressee.create_mailbox(name, options)
|
38
|
-
end
|
12
|
+
Facteur.const_set(:Mailbox, Class.new(ActiveRecord::Base))
|
13
|
+
Facteur::Mailbox.class_exec do
|
14
|
+
include Facteur::ActiveRecordMailboxModel
|
39
15
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# Sends a message to one or many addressees. The following options are available:
|
46
|
-
#
|
47
|
-
# <tt>:to</tt>:: the addressee or the list of addressees (mandatory)
|
48
|
-
# <tt>:in</tt>:: the name of the mailbox in which the message is posted (mandatory)
|
49
|
-
# <tt>:body</tt>:: the message's body (mandatory)
|
50
|
-
#
|
51
|
-
# Usage :
|
52
|
-
#
|
53
|
-
# # send a message to one addressee
|
54
|
-
# @john.send_message('message contents', :to => @peter, :in => :private_mailbox)
|
55
|
-
#
|
56
|
-
# # send a message to many addressees
|
57
|
-
# @john.send_message('message contents', :to => [@peter, @james], :in => :private_mailbox)
|
58
|
-
def send_message(message, options)
|
59
|
-
msg = nil
|
60
|
-
options[:body] = message
|
61
|
-
if options[:to].is_a? Array
|
62
|
-
options[:to].each do |addressee|
|
63
|
-
msg = send_message_to(addressee, options[:in], options[:body], options[:subject])
|
64
|
-
end
|
65
|
-
else
|
66
|
-
msg = send_message_to(options[:to], options[:in], options[:body], options[:subject])
|
16
|
+
|
17
|
+
Facteur.const_set(:Message, Class.new(ActiveRecord::Base))
|
18
|
+
Facteur::Message.class_exec do
|
19
|
+
include Facteur::ActiveRecordMessageModel
|
67
20
|
end
|
68
|
-
msg
|
69
|
-
end
|
70
|
-
|
71
|
-
# Creates a new mailbox. if a mailbox with the same name already exists, it fails and returns false. If succeeded, it creates an accessor for the new mail box and returns true.
|
72
|
-
# Example :
|
73
|
-
#
|
74
|
-
# class User < ActiveRecord::base
|
75
|
-
# include Facteur::AddresseeModel
|
76
|
-
#
|
77
|
-
# mailbox :private_mailbox
|
78
|
-
# end
|
79
|
-
#
|
80
|
-
# The previous declaration will add : User#private_mailbox
|
81
|
-
#
|
82
|
-
# # supposing that a name field exists
|
83
|
-
# user = User.new(:name => 'John')
|
84
|
-
# user.create_mailbox :public_mailbox #=> return true
|
85
|
-
# user.create_mailbox :private_mailbox #=> return false
|
86
|
-
def create_mailbox(name, options={})
|
87
|
-
mailbox = Mailbox.new(:name => name.to_s)
|
88
|
-
mailbox.addressee = self
|
89
|
-
mailbox.default = options[:default]
|
90
|
-
return false if mailbox.save == false
|
91
21
|
|
92
|
-
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
# Creates a new mailbox. if a mailbox with the same name already exists, it raises an exception. If succeeded, it creates an accessor for the new mail box and returns the created mailbox.
|
97
|
-
def create_mailbox!(name, options={})
|
98
|
-
if create_mailbox(name, options) == false
|
99
|
-
raise "Mailboxes names must be unique. Can't create '#{name}'"
|
100
|
-
end
|
101
|
-
self.send "#{name}"
|
102
|
-
end
|
22
|
+
include Facteur::ActiveRecordAddresseeModel
|
103
23
|
|
104
|
-
|
105
|
-
def method_missing(method, *args, &block)
|
106
|
-
super if method == :to_ary
|
24
|
+
elsif self.ancestors.map(&:to_s).include?("Mongoid::Document")
|
107
25
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return mailbox unless mailbox.nil?
|
113
|
-
super
|
26
|
+
Facteur.const_set(:Mailbox, Class.new)
|
27
|
+
Facteur::Mailbox.class_exec do
|
28
|
+
include Mongoid::Document
|
29
|
+
include Facteur::MongoidMailboxModel
|
114
30
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
# creates the mailboxes defined in the configuration
|
121
|
-
def create_mailboxes
|
122
|
-
self.class.mailboxes.each do |mailbox|
|
123
|
-
options = {}.merge(mailbox)
|
124
|
-
name = options.delete(:name)
|
125
|
-
create_mailbox!(name, options)
|
31
|
+
|
32
|
+
Facteur.const_set(:Message, Class.new)
|
33
|
+
Facteur::Message.class_exec do
|
34
|
+
include Mongoid::Document
|
35
|
+
include Facteur::MongoidMessageModel
|
126
36
|
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# send a message to an addressee
|
130
|
-
def send_message_to(addressee, mailbox_name, contents, subject=nil)
|
131
|
-
return false if addressee.nil? or contents.nil?
|
132
37
|
|
133
|
-
|
134
|
-
return false if mailbox_name.nil?
|
38
|
+
include Facteur::MongoidAddresseeModel
|
135
39
|
|
136
|
-
|
137
|
-
|
138
|
-
message.mailbox = addressee.send(mailbox_name)
|
139
|
-
message.body = contents
|
140
|
-
message.subject = subject
|
141
|
-
message.save
|
142
|
-
message
|
40
|
+
else
|
41
|
+
raise "Facteur only supports ActiveRecord and Mongoid"
|
143
42
|
end
|
144
43
|
end
|
145
44
|
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Facteur
|
2
|
+
module BaseAddresseeModel
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# Define a mailbox. The following options are available:
|
7
|
+
# <tt>:default</tt>:: defines the default mailbox. You must choose one default mailbox
|
8
|
+
def mailbox(name, options={})
|
9
|
+
mailbox = {:name => name}
|
10
|
+
mailbox.merge! options
|
11
|
+
mailboxes << mailbox
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the mailboxes defined for the class
|
15
|
+
def mailboxes
|
16
|
+
@mailboxes ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
# check if a mailbox is defined
|
20
|
+
def has_mailbox?(name)
|
21
|
+
@mailboxes.each do |mailbox|
|
22
|
+
return true if mailbox[:name] == name
|
23
|
+
end
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
# return the default mailbox name if set, else return nil
|
28
|
+
def default_mailbox
|
29
|
+
@mailboxes.select{ |mailbox| mailbox[:default] == true }.first[:name]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module InstanceMethods
|
34
|
+
# returns the messages sent by this addressee
|
35
|
+
def sent_messages
|
36
|
+
sent_messages_mailbox.messages
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sends a message to one or many addressees. The following options are available:
|
40
|
+
#
|
41
|
+
# <tt>:to</tt>:: the addressee or the list of addressees (mandatory)
|
42
|
+
# <tt>:in</tt>:: the name of the mailbox in which the message is posted (mandatory)
|
43
|
+
# <tt>:body</tt>:: the message's body (mandatory)
|
44
|
+
#
|
45
|
+
# Usage :
|
46
|
+
#
|
47
|
+
# # send a message to one addressee
|
48
|
+
# @john.send_message('message contents', :to => @peter, :in => :private_mailbox)
|
49
|
+
#
|
50
|
+
# # send a message to many addressees
|
51
|
+
# @john.send_message('message contents', :to => [@peter, @james], :in => :private_mailbox)
|
52
|
+
def send_message(message, options)
|
53
|
+
options[:body] = message
|
54
|
+
if options[:to].respond_to?(:each)
|
55
|
+
options[:to].each { |addressee| send_message_to(addressee, options[:in], options[:body], options[:subject]) }
|
56
|
+
else
|
57
|
+
send_message_to(options[:to], options[:in], options[:body], options[:subject])
|
58
|
+
end
|
59
|
+
|
60
|
+
store_in_sent_messages(message, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Creates a new mailbox. if a mailbox with the same name already exists, it fails and returns false. If succeeded, it creates an accessor for the new mail box and returns true.
|
64
|
+
# Example :
|
65
|
+
#
|
66
|
+
# class User < ActiveRecord::base
|
67
|
+
# include Facteur::AddresseeModel
|
68
|
+
#
|
69
|
+
# mailbox :private_mailbox
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# The previous declaration will add : User#private_mailbox
|
73
|
+
#
|
74
|
+
# # supposing that a name field exists
|
75
|
+
# user = User.new(:name => 'John')
|
76
|
+
# user.create_mailbox :public_mailbox #=> return true
|
77
|
+
# user.create_mailbox :private_mailbox #=> return false
|
78
|
+
def create_mailbox(name, options={})
|
79
|
+
mailbox = mailboxes.build(:name => name.to_s, :default => options[:default])
|
80
|
+
return false if mailbox.save == false
|
81
|
+
mailbox
|
82
|
+
end
|
83
|
+
|
84
|
+
# Creates a new mailbox. if a mailbox with the same name already exists, it raises an exception. If succeeded, it creates an accessor for the new mail box and returns the created mailbox.
|
85
|
+
def create_mailbox!(name, options={})
|
86
|
+
if create_mailbox(name, options) == false
|
87
|
+
raise "Mailboxes names must be unique. Can't create '#{name}'"
|
88
|
+
end
|
89
|
+
self.send "#{name}"
|
90
|
+
end
|
91
|
+
|
92
|
+
# generates the mailboxes accessors
|
93
|
+
def method_missing(method, *args, &block)
|
94
|
+
begin
|
95
|
+
super
|
96
|
+
rescue NoMethodError, NameError
|
97
|
+
mailbox = self.mailboxes.where(:name => method.to_s).first
|
98
|
+
if mailbox.nil?
|
99
|
+
super unless self.class.has_mailbox?(method)
|
100
|
+
|
101
|
+
# if the unknown method matches one of the Model mailboxes, then the mailbox is created
|
102
|
+
create_mailbox(method, self.class.mailboxes.select{ |m| m[:name] == method }.first)
|
103
|
+
else
|
104
|
+
return mailbox
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# redefine the comparison method because for some weirds reasons, the original fails
|
110
|
+
def ==(comparison_object)
|
111
|
+
comparison_object.equal?(self) ||
|
112
|
+
(self.class.to_s == comparison_object.class.to_s &&
|
113
|
+
comparison_object.id == id && !comparison_object.new_record?)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# return the sent messages mailbox
|
119
|
+
def sent_messages_mailbox
|
120
|
+
mailbox = self.mailboxes.where(:name => "sent_messages_mailbox").first
|
121
|
+
mailbox || create_mailbox("sent_messages_mailbox")
|
122
|
+
end
|
123
|
+
|
124
|
+
# creates the mailboxes defined in the configuration
|
125
|
+
def create_mailboxes
|
126
|
+
self.class.mailboxes.each do |mailbox|
|
127
|
+
options = {}.merge(mailbox)
|
128
|
+
name = options.delete(:name)
|
129
|
+
create_mailbox!(name, options)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# send a message to an addressee
|
134
|
+
def send_message_to(addressee, mailbox_name, contents, subject=nil)
|
135
|
+
return false if addressee.nil? or contents.nil?
|
136
|
+
|
137
|
+
mailbox_name = self.class.default_mailbox if mailbox_name.nil?
|
138
|
+
return false if mailbox_name.nil?
|
139
|
+
|
140
|
+
message = addressee.send(mailbox_name).messages.build(:subject => subject, :body => contents)
|
141
|
+
message.author = self
|
142
|
+
message.save ? message : false
|
143
|
+
end
|
144
|
+
|
145
|
+
# saves a message in the sent messages mailbox
|
146
|
+
def store_in_sent_messages(message, options)
|
147
|
+
# the addressees must be given
|
148
|
+
return false if options[:to].blank?
|
149
|
+
|
150
|
+
sent_message = sent_messages_mailbox.messages.build(:subject => options[:subject], :body => options[:body])
|
151
|
+
sent_message.author = self
|
152
|
+
|
153
|
+
if options[:to].respond_to?(:each)
|
154
|
+
options[:to].each { |addressee| sent_message.addressees << addressee }
|
155
|
+
else
|
156
|
+
sent_message.addressees << options[:to]
|
157
|
+
end
|
158
|
+
|
159
|
+
sent_message.save ? sent_message : false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|