muck-invites 0.1.3 → 0.1.4
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 +35 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/app/controllers/muck/invites_controller.rb +15 -4
- data/db/migrate/20091128170318_make_invites_polymorphic.rb +27 -0
- data/lib/active_record/acts/muck_invite.rb +7 -26
- data/lib/active_record/acts/muck_invitee.rb +57 -0
- data/lib/active_record/acts/muck_inviter.rb +18 -9
- data/lib/muck_invites.rb +1 -0
- data/muck-invites.gemspec +10 -3
- data/test/rails_root/app/models/invite.rb +1 -2
- data/test/rails_root/app/models/invitee.rb +4 -0
- data/test/rails_root/config/database.yml +13 -20
- data/test/rails_root/db/migrate/20091128170318_make_invites_polymorphic.rb +27 -0
- data/test/rails_root/test/functional/invites_controller_test.rb +10 -4
- data/test/rails_root/test/unit/invite_test.rb +6 -127
- data/test/rails_root/test/unit/invitee_test.rb +146 -0
- data/test/rails_root/test/unit/user_test.rb +3 -3
- metadata +10 -3
- data/app/models/user_invite.rb +0 -6
data/README.rdoc
CHANGED
@@ -1,6 +1,39 @@
|
|
1
1
|
= Muck Invites
|
2
|
-
|
2
|
+
Make it easy to let users invite other users.
|
3
3
|
|
4
4
|
== Setup
|
5
5
|
|
6
|
-
|
6
|
+
=== Inviter model
|
7
|
+
Add 'acts_as_muck_inviter' to the class that you wish to have do the inviting. This is commonly the user model, but
|
8
|
+
might also be another model - for example Event.
|
9
|
+
|
10
|
+
class User < ActiveRecord::Base
|
11
|
+
acts_as_authentic do |c|
|
12
|
+
c.crypto_provider = Authlogic::CryptoProviders::BCrypt
|
13
|
+
end
|
14
|
+
acts_as_muck_user
|
15
|
+
acts_as_muck_inviter
|
16
|
+
end
|
17
|
+
|
18
|
+
or
|
19
|
+
|
20
|
+
class Event < ActiveRecord::Base
|
21
|
+
acts_as_muck_inviter
|
22
|
+
end
|
23
|
+
|
24
|
+
=== Other models
|
25
|
+
These models are required for the invite system to function and must be named as specified. Addition functionality
|
26
|
+
can be added to each model as needed.
|
27
|
+
|
28
|
+
Create an Invitee model:
|
29
|
+
class Invitee < ActiveRecord::Base
|
30
|
+
acts_as_muck_invitee
|
31
|
+
end
|
32
|
+
|
33
|
+
Create an Invite model:
|
34
|
+
class Invite < ActiveRecord::Base
|
35
|
+
acts_as_muck_invite
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
Copyright (c) 2009 Tatemae.com, released under the MIT license
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
@@ -38,10 +38,17 @@ class Muck::InvitesController < ApplicationController
|
|
38
38
|
|
39
39
|
def create
|
40
40
|
if params[:emails]
|
41
|
-
current_user.invite(params[:emails])
|
42
|
-
|
43
|
-
end
|
44
|
-
|
41
|
+
current_user.invite(params[:emails], current_user)
|
42
|
+
message = t('muck.invites.create_success', :emails => params[:emails].join(', '), :app_name => GlobalConfig.application_name)
|
43
|
+
end
|
44
|
+
respond_to do |format|
|
45
|
+
format.html do
|
46
|
+
flash[:notice] = message
|
47
|
+
redirect_to('/')
|
48
|
+
end
|
49
|
+
format.pjs { render :text => message }
|
50
|
+
end
|
51
|
+
|
45
52
|
rescue ActiveRecord::RecordInvalid => ex
|
46
53
|
if @invite
|
47
54
|
errors = @invite.errors.full_messages.to_sentence
|
@@ -49,6 +56,10 @@ class Muck::InvitesController < ApplicationController
|
|
49
56
|
errors = ex
|
50
57
|
end
|
51
58
|
flash[:error] = t('muck.invites.create_error', :errors => errors)
|
59
|
+
respond_to do |format|
|
60
|
+
format.html { render :template => 'invites/new' }
|
61
|
+
format.pjs { render :template => 'invites/new', :layout => false }
|
62
|
+
end
|
52
63
|
end
|
53
64
|
|
54
65
|
protected
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class MakeInvitesPolymorphic < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
drop_table :user_invites
|
5
|
+
rename_table :invites, :invitees
|
6
|
+
create_table :invites, :force => true do |t|
|
7
|
+
t.integer :user_id
|
8
|
+
t.integer :invitee_id, :null => false
|
9
|
+
t.integer :inviter_id, :null => false
|
10
|
+
t.string :inviter_type
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
add_index :invites, ["inviter_id", "inviter_type"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.down
|
17
|
+
drop_table :invites
|
18
|
+
rename_table :invitees, :invites
|
19
|
+
create_table :user_invites, :force => true do |t|
|
20
|
+
t.integer :user_id, :null => false
|
21
|
+
t.integer :invite_id, :null => false
|
22
|
+
t.timestamp :created_at, :null => false
|
23
|
+
end
|
24
|
+
add_index :user_invites, ["user_id"]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -8,21 +8,17 @@ module ActiveRecord
|
|
8
8
|
module ClassMethods
|
9
9
|
|
10
10
|
def acts_as_muck_invite(options = {})
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
belongs_to :invitee
|
12
|
+
belongs_to :inviter, :polymorphic => true
|
13
|
+
# User and inviter might be the same. For example, if a user invites their friends then user == inviter.
|
14
|
+
# However if inviter is something else for example an Event then having a user field let's us quickly
|
15
|
+
# discover who created the invite. (Used by who_invited?)
|
16
|
+
belongs_to :user
|
17
|
+
|
16
18
|
named_scope :by_newest, :order => "created_at DESC"
|
17
19
|
named_scope :by_oldest, :order => "created_at ASC"
|
18
20
|
named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
|
19
21
|
|
20
|
-
email_name_regex = '[\w\.%\+\-]+'.freeze
|
21
|
-
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'.freeze
|
22
|
-
domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'.freeze
|
23
|
-
email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
24
|
-
|
25
|
-
validates_format_of :email, :with => email_regex, :message => 'does not look like a valid email address.'
|
26
22
|
|
27
23
|
include ActiveRecord::Acts::MuckInvite::InstanceMethods
|
28
24
|
extend ActiveRecord::Acts::MuckInvite::SingletonMethods
|
@@ -32,25 +28,10 @@ module ActiveRecord
|
|
32
28
|
|
33
29
|
# class methods
|
34
30
|
module SingletonMethods
|
35
|
-
|
36
|
-
def who_invited?(email, id = nil)
|
37
|
-
users = []
|
38
|
-
|
39
|
-
if !id.nil?
|
40
|
-
invite = Invite.find(id)
|
41
|
-
users |= invite.users if !invite.nil?
|
42
|
-
end
|
43
|
-
|
44
|
-
invite = Invite.find_by_email(email)
|
45
|
-
users |= invite.users if !invite.nil?
|
46
|
-
|
47
|
-
users
|
48
|
-
end
|
49
31
|
end
|
50
32
|
|
51
33
|
# All the methods available to a record that has had <tt>acts_as_muck_invite</tt> specified.
|
52
34
|
module InstanceMethods
|
53
|
-
|
54
35
|
end
|
55
36
|
end
|
56
37
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Acts #:nodoc:
|
3
|
+
module MuckInvitee #:nodoc:
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def acts_as_muck_invitee(options = {})
|
11
|
+
|
12
|
+
has_many :invites
|
13
|
+
has_many :users, :through => :invites
|
14
|
+
validates_presence_of :email
|
15
|
+
|
16
|
+
named_scope :by_newest, :order => "created_at DESC"
|
17
|
+
named_scope :by_oldest, :order => "created_at ASC"
|
18
|
+
named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
|
19
|
+
|
20
|
+
email_name_regex = '[\w\.%\+\-]+'.freeze
|
21
|
+
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'.freeze
|
22
|
+
domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'.freeze
|
23
|
+
email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
24
|
+
|
25
|
+
validates_format_of :email, :with => email_regex, :message => 'does not look like a valid email address.'
|
26
|
+
|
27
|
+
include ActiveRecord::Acts::MuckInvitee::InstanceMethods
|
28
|
+
extend ActiveRecord::Acts::MuckInvitee::SingletonMethods
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# class methods
|
34
|
+
module SingletonMethods
|
35
|
+
|
36
|
+
def who_invited?(email, invitee_id = nil)
|
37
|
+
users = []
|
38
|
+
|
39
|
+
if !invitee_id.nil?
|
40
|
+
invite = Invitee.find(invitee_id)
|
41
|
+
users |= invite.users if !invite.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
invite = Invitee.find_by_email(email)
|
45
|
+
users |= invite.users if !invite.nil?
|
46
|
+
|
47
|
+
users
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# All the methods available to a record that has had <tt>acts_as_muck_invitee</tt> specified.
|
52
|
+
module InstanceMethods
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -8,10 +8,8 @@ module ActiveRecord
|
|
8
8
|
module ClassMethods
|
9
9
|
|
10
10
|
def acts_as_muck_inviter(options = {})
|
11
|
-
|
12
|
-
has_many :
|
13
|
-
has_many :invites, :through => :user_invites
|
14
|
-
|
11
|
+
has_many :invites, :as => :inviter
|
12
|
+
has_many :invitees, :through => :invites
|
15
13
|
named_scope :by_newest, :order => "created_at DESC"
|
16
14
|
named_scope :by_oldest, :order => "created_at ASC"
|
17
15
|
named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
|
@@ -34,8 +32,14 @@ module ActiveRecord
|
|
34
32
|
# All the methods available to a record that has had <tt>acts_as_muck_inviter</tt> specified.
|
35
33
|
module InstanceMethods
|
36
34
|
|
35
|
+
# Gets all emails have been invited
|
36
|
+
def invitee_emails
|
37
|
+
invitees.map(&:email)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sends out notification email and adds an activity to each of the inviters activity feeds
|
37
41
|
def notify_inviters(invite_id = nil)
|
38
|
-
inviters =
|
42
|
+
inviters = Invitee.who_invited?(self.email, invite_id)
|
39
43
|
if inviters.size > 0
|
40
44
|
content = I18n.t('muck.activities.joined_status', :name => self.full_name, :application_name => GlobalConfig.application_name)
|
41
45
|
inviters.each do |inviter|
|
@@ -49,13 +53,18 @@ module ActiveRecord
|
|
49
53
|
|
50
54
|
end
|
51
55
|
|
52
|
-
def invite(emails)
|
56
|
+
def invite(emails, user)
|
53
57
|
emails = emails.split(/[, ]/) if !emails.is_a?(Array)
|
54
|
-
emails = emails.find_all { |email| !email.blank?}
|
58
|
+
emails = emails.find_all { |email| !email.blank? }
|
59
|
+
emails = emails.flatten.collect { |email| email.strip }
|
55
60
|
raise I18n.t('muck.invites.no_email_error') if emails.blank?
|
61
|
+
check_emails = invitee_emails
|
56
62
|
emails.each do |email|
|
57
|
-
|
58
|
-
|
63
|
+
if !check_emails.include?(email)
|
64
|
+
check_emails << email
|
65
|
+
invitee = Invitee.find_by_email(email) || Invitee.create!(:email => email)
|
66
|
+
Invite.create!(:inviter => self, :invitee => invitee, :user => user)
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
data/lib/muck_invites.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
ActiveRecord::Base.class_eval { include ActiveRecord::Acts::MuckInvitee }
|
1
2
|
ActiveRecord::Base.class_eval { include ActiveRecord::Acts::MuckInvite }
|
2
3
|
ActiveRecord::Base.class_eval { include ActiveRecord::Acts::MuckInviter }
|
3
4
|
I18n.load_path += Dir[ File.join(File.dirname(__FILE__), '..', 'locales', '*.{rb,yml}') ]
|
data/muck-invites.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{muck-invites}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Ball, Joel Duffin"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-30}
|
13
13
|
s.description = %q{The invite engine for the muck system.}
|
14
14
|
s.email = %q{justin@tatemae.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
"VERSION",
|
24
24
|
"app/controllers/muck/invites_controller.rb",
|
25
25
|
"app/models/invite_mailer.rb",
|
26
|
-
"app/models/user_invite.rb",
|
27
26
|
"app/views/invite_mailer/invite_notification.text.html.erb",
|
28
27
|
"app/views/invite_mailer/invite_notification.text.plain.erb",
|
29
28
|
"app/views/invite_mailer/invited_joined_notification.text.html.erb",
|
@@ -32,8 +31,10 @@ Gem::Specification.new do |s|
|
|
32
31
|
"app/views/invites/new.html.erb",
|
33
32
|
"config/muck_invites_routes.rb",
|
34
33
|
"db/migrate/20090928213532_create_invites.rb",
|
34
|
+
"db/migrate/20091128170318_make_invites_polymorphic.rb",
|
35
35
|
"install.rb",
|
36
36
|
"lib/active_record/acts/muck_invite.rb",
|
37
|
+
"lib/active_record/acts/muck_invitee.rb",
|
37
38
|
"lib/active_record/acts/muck_inviter.rb",
|
38
39
|
"lib/muck_invites.rb",
|
39
40
|
"lib/muck_invites/initialize_routes.rb",
|
@@ -96,6 +97,7 @@ Gem::Specification.new do |s|
|
|
96
97
|
"test/rails_root/app/models/.keep",
|
97
98
|
"test/rails_root/app/models/activity.rb",
|
98
99
|
"test/rails_root/app/models/invite.rb",
|
100
|
+
"test/rails_root/app/models/invitee.rb",
|
99
101
|
"test/rails_root/app/models/user.rb",
|
100
102
|
"test/rails_root/app/models/user_session.rb",
|
101
103
|
"test/rails_root/app/views/default/index.html.erb",
|
@@ -124,6 +126,7 @@ Gem::Specification.new do |s|
|
|
124
126
|
"test/rails_root/db/migrate/20090703055724_add_contents.rb",
|
125
127
|
"test/rails_root/db/migrate/20090704220055_create_slugs.rb",
|
126
128
|
"test/rails_root/db/migrate/20090928213532_create_invites.rb",
|
129
|
+
"test/rails_root/db/migrate/20091128170318_make_invites_polymorphic.rb",
|
127
130
|
"test/rails_root/features/comments.feature",
|
128
131
|
"test/rails_root/features/step_definitions/comment_steps.rb",
|
129
132
|
"test/rails_root/features/step_definitions/common_steps.rb",
|
@@ -331,6 +334,7 @@ Gem::Specification.new do |s|
|
|
331
334
|
"test/rails_root/test/unit/contacts_test.rb",
|
332
335
|
"test/rails_root/test/unit/invite_mailer_test.rb",
|
333
336
|
"test/rails_root/test/unit/invite_test.rb",
|
337
|
+
"test/rails_root/test/unit/invitee_test.rb",
|
334
338
|
"test/rails_root/test/unit/user_test.rb",
|
335
339
|
"test/rails_root/vendor/plugins/jrails/CHANGELOG",
|
336
340
|
"test/rails_root/vendor/plugins/jrails/LICENSE",
|
@@ -365,6 +369,7 @@ Gem::Specification.new do |s|
|
|
365
369
|
"test/rails_root/app/helpers/application_helper.rb",
|
366
370
|
"test/rails_root/app/models/activity.rb",
|
367
371
|
"test/rails_root/app/models/invite.rb",
|
372
|
+
"test/rails_root/app/models/invitee.rb",
|
368
373
|
"test/rails_root/app/models/user.rb",
|
369
374
|
"test/rails_root/app/models/user_session.rb",
|
370
375
|
"test/rails_root/config/boot.rb",
|
@@ -388,6 +393,7 @@ Gem::Specification.new do |s|
|
|
388
393
|
"test/rails_root/db/migrate/20090703055724_add_contents.rb",
|
389
394
|
"test/rails_root/db/migrate/20090704220055_create_slugs.rb",
|
390
395
|
"test/rails_root/db/migrate/20090928213532_create_invites.rb",
|
396
|
+
"test/rails_root/db/migrate/20091128170318_make_invites_polymorphic.rb",
|
391
397
|
"test/rails_root/features/step_definitions/comment_steps.rb",
|
392
398
|
"test/rails_root/features/step_definitions/common_steps.rb",
|
393
399
|
"test/rails_root/features/step_definitions/webrat_steps.rb",
|
@@ -400,6 +406,7 @@ Gem::Specification.new do |s|
|
|
400
406
|
"test/rails_root/test/unit/contacts_test.rb",
|
401
407
|
"test/rails_root/test/unit/invite_mailer_test.rb",
|
402
408
|
"test/rails_root/test/unit/invite_test.rb",
|
409
|
+
"test/rails_root/test/unit/invitee_test.rb",
|
403
410
|
"test/rails_root/test/unit/user_test.rb",
|
404
411
|
"test/rails_root/vendor/plugins/jrails/init.rb",
|
405
412
|
"test/rails_root/vendor/plugins/jrails/install.rb",
|
@@ -1,23 +1,16 @@
|
|
1
1
|
development:
|
2
|
-
adapter:
|
3
|
-
database:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
2
|
+
adapter: mysql
|
3
|
+
database: muck_invites_development
|
4
|
+
username: root
|
5
|
+
password:
|
6
|
+
host: localhost
|
7
|
+
encoding: utf8
|
8
|
+
test:
|
9
|
+
adapter: mysql
|
10
|
+
database: muck_invites_test
|
11
|
+
username: root
|
12
|
+
password:
|
13
|
+
host: localhost
|
14
|
+
encoding: utf8
|
16
15
|
cucumber:
|
17
16
|
<<: *TEST
|
18
|
-
cucumber:
|
19
|
-
<<: *TEST
|
20
|
-
cucumber:
|
21
|
-
<<: *TEST
|
22
|
-
cucumber:
|
23
|
-
<<: *TEST
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class MakeInvitesPolymorphic < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
drop_table :user_invites
|
5
|
+
rename_table :invites, :invitees
|
6
|
+
create_table :invites, :force => true do |t|
|
7
|
+
t.integer :user_id
|
8
|
+
t.integer :invitee_id, :null => false
|
9
|
+
t.integer :inviter_id, :null => false
|
10
|
+
t.string :inviter_type
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
add_index :invites, ["inviter_id", "inviter_type"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.down
|
17
|
+
drop_table :invites
|
18
|
+
rename_table :invitees, :invites
|
19
|
+
create_table :user_invites, :force => true do |t|
|
20
|
+
t.integer :user_id, :null => false
|
21
|
+
t.integer :invite_id, :null => false
|
22
|
+
t.timestamp :created_at, :null => false
|
23
|
+
end
|
24
|
+
add_index :user_invites, ["user_id"]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -53,13 +53,19 @@ class Muck::InvitesControllerTest < ActionController::TestCase
|
|
53
53
|
should_render_template :get_contacts
|
54
54
|
end
|
55
55
|
|
56
|
-
context "create
|
57
|
-
should "
|
58
|
-
assert_difference "Invite.count" do
|
59
|
-
post :create, :emails => [[Factory.next(:
|
56
|
+
context "POST to create" do
|
57
|
+
should "create a invite s" do
|
58
|
+
assert_difference "Invite.count", 2 do
|
59
|
+
post :create, :emails => [[Factory.next(:email),Factory.next(:email)]]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
should "create a invitee" do
|
63
|
+
assert_difference "Invite.count", 2 do
|
64
|
+
post :create, :emails => [[Factory.next(:email),Factory.next(:email)]]
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
68
|
+
|
63
69
|
end
|
64
70
|
|
65
71
|
end
|
@@ -5,136 +5,15 @@ class InviteTest < ActiveSupport::TestCase
|
|
5
5
|
context "Invite" do
|
6
6
|
setup do
|
7
7
|
@user = Factory(:user)
|
8
|
-
@
|
9
|
-
@
|
8
|
+
@invitee = Factory(:invitee)
|
9
|
+
@invite = Invite.create(:inviter => @user, :invitee => @invitee, :user => @user)
|
10
10
|
end
|
11
11
|
|
12
12
|
subject { @invite }
|
13
|
-
should_validate_presence_of :email
|
14
|
-
should_have_many :users
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
assert_no_difference 'Invite.count' do
|
21
|
-
u = Factory.build(:invite, :email => nil)
|
22
|
-
assert !u.valid?
|
23
|
-
assert u.errors.on(:email)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
should "not create new invites when more than one person invites the same email address" do
|
28
|
-
assert_no_difference 'Invite.count' do
|
29
|
-
u = Factory(:user)
|
30
|
-
u.invites << @invite
|
31
|
-
u.save!
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
should "be able to see how many inviters it has" do
|
36
|
-
assert_equal 1, @invite.users.size
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
context "User" do
|
42
|
-
setup do
|
43
|
-
@user = Factory(:user)
|
44
|
-
end
|
45
|
-
|
46
|
-
subject { @user }
|
47
|
-
|
48
|
-
should "be able to call invite with a single email address" do
|
49
|
-
@user.invite(Factory.next(:email))
|
50
|
-
assert_equal 1, @user.invites.size
|
51
|
-
end
|
52
|
-
|
53
|
-
should "be able to call invite with a string specifying a space delimited list of email addresses" do
|
54
|
-
@user.invite(Factory.next(:email) + ' ' + Factory.next(:email))
|
55
|
-
assert_equal 2, @user.invites.size
|
56
|
-
end
|
57
|
-
|
58
|
-
should "be able to call invite with a string specifying a comma delimited list of email addresses" do
|
59
|
-
@user.invite(Factory.next(:email) + ', ' + Factory.next(:email) + ',' + Factory.next(:email) + ',')
|
60
|
-
assert_equal 3, @user.invites.size
|
61
|
-
end
|
62
|
-
|
63
|
-
should "be able to call invite with an array of email addresses" do
|
64
|
-
@user.invite([Factory.next(:email),Factory.next(:email)])
|
65
|
-
assert_equal 2, @user.invites.size
|
66
|
-
end
|
67
|
-
|
68
|
-
should "be able to look up who invited them by email" do
|
69
|
-
inviter = Factory(:user)
|
70
|
-
inviter.invites << Factory.build(:invite, :email => @user.email)
|
71
|
-
assert_equal Invite.who_invited?(@user.email).first, inviter
|
72
|
-
end
|
73
|
-
|
74
|
-
should "be able to look up who invited them by id" do
|
75
|
-
invite = Factory.build(:invite, :email => @user.email)
|
76
|
-
|
77
|
-
inviter = Factory(:user)
|
78
|
-
inviter.invites << Factory.build(:invite, :email => @user.email)
|
79
|
-
assert_equal Invite.who_invited?(@user.email).first, inviter
|
80
|
-
end
|
81
|
-
|
82
|
-
should "look up multiple inviters by email" do
|
83
|
-
invite = Factory.build(:invite, :email => @user.email)
|
84
|
-
|
85
|
-
inviter1 = Factory(:user)
|
86
|
-
inviter1.invites << invite
|
87
|
-
|
88
|
-
inviter2 = Factory(:user)
|
89
|
-
inviter2.invites << invite
|
90
|
-
|
91
|
-
inviters = Invite.who_invited?(@user.email)
|
92
|
-
assert_equal 2, inviters.count
|
93
|
-
assert inviters.include?(inviter1)
|
94
|
-
assert inviters.include?(inviter2)
|
95
|
-
end
|
96
|
-
|
97
|
-
should "not create new user invites if the user has invited them before" do
|
98
|
-
user = Factory(:user)
|
99
|
-
email = Factory.next(:email)
|
100
|
-
user.invite(email)
|
101
|
-
user.invite(email)
|
102
|
-
assert_equal 1, Invite.all.size
|
103
|
-
assert_equal 1, user.invites.size
|
104
|
-
end
|
14
|
+
should_belong_to :user
|
15
|
+
should_belong_to :inviter
|
16
|
+
should_belong_to :invitee
|
17
|
+
|
105
18
|
end
|
106
|
-
|
107
|
-
context "Always" do
|
108
|
-
should "be able to look up who invited them by id and by email" do
|
109
|
-
user1 = Factory(:user)
|
110
|
-
invite1 = Factory(:invite)
|
111
|
-
user1.invites << invite1
|
112
|
-
|
113
|
-
user2 = Factory(:user)
|
114
|
-
invite2 = Factory(:invite)
|
115
|
-
user2.invites << invite2
|
116
|
-
|
117
|
-
inviters = Invite.who_invited?(invite1.email, invite2.id)
|
118
|
-
assert_equal 2, inviters.size
|
119
|
-
assert inviters.include?(user1)
|
120
|
-
assert inviters.include?(user2)
|
121
|
-
end
|
122
|
-
|
123
|
-
should "notify inviters when a new user joins" do
|
124
|
-
user1 = Factory(:user)
|
125
|
-
invite1 = Factory(:invite)
|
126
|
-
user1.invites << invite1
|
127
|
-
|
128
|
-
user2 = Factory(:user)
|
129
|
-
invite2 = Factory(:invite)
|
130
|
-
user2.invites << invite2
|
131
|
-
|
132
|
-
user3 = Factory.build(:user, :email => invite1.email)
|
133
|
-
|
134
|
-
assert_nothing_raised do
|
135
|
-
user3.notify_inviters(invite2.id)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
19
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class InviteeTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
context "Invitee" do
|
6
|
+
setup do
|
7
|
+
@user = Factory(:user)
|
8
|
+
@invitee = Factory(:invitee)
|
9
|
+
@invite = Invite.create(:inviter => @user, :invitee => @invitee, :user => @user)
|
10
|
+
@user.reload
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { @invitee }
|
14
|
+
should_validate_presence_of :email
|
15
|
+
should_have_many :users
|
16
|
+
|
17
|
+
should_allow_values_for :email, 'a@x.com', 'de.veloper@example.com'
|
18
|
+
should_not_allow_values_for :email, 'example.com', '@example.com', 'developer@example', 'developer', :message => 'does not look like a valid email address.'
|
19
|
+
|
20
|
+
should "require email" do
|
21
|
+
assert_no_difference 'Invite.count' do
|
22
|
+
u = Factory.build(:invitee, :email => nil)
|
23
|
+
assert !u.valid?
|
24
|
+
assert u.errors.on(:email)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
should "not create new invites when more than one person invites the same email address" do
|
29
|
+
assert_no_difference 'Invite.count' do
|
30
|
+
u = Factory(:user)
|
31
|
+
u.invites << @invite
|
32
|
+
u.save!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "be able to see how many inviters it has" do
|
37
|
+
assert_equal 1, @invitee.users.size
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context "User" do
|
43
|
+
setup do
|
44
|
+
@user = Factory(:user)
|
45
|
+
end
|
46
|
+
|
47
|
+
subject { @user }
|
48
|
+
|
49
|
+
should "be able to call invite with a single email address" do
|
50
|
+
@user.invite(Factory.next(:email), @user)
|
51
|
+
assert_equal 1, @user.invites.size
|
52
|
+
end
|
53
|
+
|
54
|
+
should "be able to call invite with a string specifying a space delimited list of email addresses" do
|
55
|
+
@user.invite(Factory.next(:email) + ' ' + Factory.next(:email), @user)
|
56
|
+
assert_equal 2, @user.invites.size
|
57
|
+
end
|
58
|
+
|
59
|
+
should "be able to call invite with a string specifying a comma delimited list of email addresses" do
|
60
|
+
@user.invite(Factory.next(:email) + ', ' + Factory.next(:email) + ',' + Factory.next(:email) + ',', @user)
|
61
|
+
assert_equal 3, @user.invites.size
|
62
|
+
end
|
63
|
+
|
64
|
+
should "be able to call invite with an array of email addresses" do
|
65
|
+
@user.invite([Factory.next(:email),Factory.next(:email)], @user)
|
66
|
+
assert_equal 2, @user.invites.size
|
67
|
+
end
|
68
|
+
|
69
|
+
should "be able to look up who invited them by email" do
|
70
|
+
inviter = Factory(:user)
|
71
|
+
invitee = Factory.build(:invitee, :email => @user.email)
|
72
|
+
inviter.invites << Invite.create!(:inviter => inviter, :user => inviter, :invitee => invitee)
|
73
|
+
assert_equal Invitee.who_invited?(@user.email).first, inviter
|
74
|
+
end
|
75
|
+
|
76
|
+
should "be able to look up who invited them by id" do
|
77
|
+
invite = Factory.build(:invitee, :email => @user.email)
|
78
|
+
|
79
|
+
inviter = Factory(:user)
|
80
|
+
invitee = Factory.build(:invitee, :email => @user.email)
|
81
|
+
inviter.invites << Invite.create!(:inviter => inviter, :user => inviter, :invitee => invitee)
|
82
|
+
assert_equal Invitee.who_invited?(@user.email).first, inviter
|
83
|
+
end
|
84
|
+
|
85
|
+
should "look up multiple inviters by email" do
|
86
|
+
invitee = Factory.build(:invitee, :email => @user.email)
|
87
|
+
|
88
|
+
inviter1 = Factory(:user)
|
89
|
+
inviter1.invites << Invite.create!(:inviter => inviter1, :user => inviter1, :invitee => invitee)
|
90
|
+
|
91
|
+
inviter2 = Factory(:user)
|
92
|
+
inviter2.invites << Invite.create!(:inviter => inviter2, :user => inviter2, :invitee => invitee)
|
93
|
+
|
94
|
+
inviters = Invitee.who_invited?(@user.email)
|
95
|
+
assert_equal 2, inviters.count
|
96
|
+
assert inviters.include?(inviter1)
|
97
|
+
assert inviters.include?(inviter2)
|
98
|
+
end
|
99
|
+
|
100
|
+
should "not create new user invites if the user has invited them before" do
|
101
|
+
user = Factory(:user)
|
102
|
+
email = Factory.next(:email)
|
103
|
+
assert_difference "Invite.count" do
|
104
|
+
user.invite(email, user)
|
105
|
+
end
|
106
|
+
user.reload # if you don't reload the invite just created won't show up.
|
107
|
+
assert_no_difference "Invite.count" do
|
108
|
+
user.invite(email, user)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "Always" do
|
114
|
+
should "be able to look up who invited them by id and by email" do
|
115
|
+
user1 = Factory(:user)
|
116
|
+
invitee1 = Factory(:invitee)
|
117
|
+
user1.invites << Invite.create!(:inviter => user1, :user => user1, :invitee => invitee1)
|
118
|
+
|
119
|
+
user2 = Factory(:user)
|
120
|
+
invitee2 = Factory(:invitee)
|
121
|
+
user2.invites << Invite.create!(:inviter => user2, :user => user2, :invitee => invitee2)
|
122
|
+
|
123
|
+
inviters = Invitee.who_invited?(invitee1.email, invitee2.id)
|
124
|
+
assert_equal 2, inviters.size
|
125
|
+
assert inviters.include?(user1)
|
126
|
+
assert inviters.include?(user2)
|
127
|
+
end
|
128
|
+
|
129
|
+
should "notify inviters when a new user joins" do
|
130
|
+
user1 = Factory(:user)
|
131
|
+
invitee1 = Factory(:invitee)
|
132
|
+
user1.invites << Invite.create!(:inviter => user1, :user => user1, :invitee => invitee1)
|
133
|
+
|
134
|
+
user2 = Factory(:user)
|
135
|
+
invitee2 = Factory(:invitee)
|
136
|
+
user2.invites << Invite.create!(:inviter => user2, :user => user2, :invitee => invitee2)
|
137
|
+
|
138
|
+
user3 = Factory.build(:user, :email => invitee1.email)
|
139
|
+
|
140
|
+
assert_nothing_raised do
|
141
|
+
user3.notify_inviters(invitee2.id)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -5,9 +5,9 @@ class UserTest < ActiveSupport::TestCase
|
|
5
5
|
context "A class that is inviteable" do
|
6
6
|
setup do
|
7
7
|
@user = Factory(:user)
|
8
|
-
|
9
|
-
|
10
|
-
@user.
|
8
|
+
@invitee = Factory(:invitee)
|
9
|
+
Invite.create!(:inviter => @user, :invitee => @invitee, :user => @user)
|
10
|
+
@user.reload
|
11
11
|
end
|
12
12
|
|
13
13
|
should "have invites" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: muck-invites
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Ball, Joel Duffin
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-30 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,6 @@ files:
|
|
48
48
|
- VERSION
|
49
49
|
- app/controllers/muck/invites_controller.rb
|
50
50
|
- app/models/invite_mailer.rb
|
51
|
-
- app/models/user_invite.rb
|
52
51
|
- app/views/invite_mailer/invite_notification.text.html.erb
|
53
52
|
- app/views/invite_mailer/invite_notification.text.plain.erb
|
54
53
|
- app/views/invite_mailer/invited_joined_notification.text.html.erb
|
@@ -57,8 +56,10 @@ files:
|
|
57
56
|
- app/views/invites/new.html.erb
|
58
57
|
- config/muck_invites_routes.rb
|
59
58
|
- db/migrate/20090928213532_create_invites.rb
|
59
|
+
- db/migrate/20091128170318_make_invites_polymorphic.rb
|
60
60
|
- install.rb
|
61
61
|
- lib/active_record/acts/muck_invite.rb
|
62
|
+
- lib/active_record/acts/muck_invitee.rb
|
62
63
|
- lib/active_record/acts/muck_inviter.rb
|
63
64
|
- lib/muck_invites.rb
|
64
65
|
- lib/muck_invites/initialize_routes.rb
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- test/rails_root/app/models/.keep
|
122
123
|
- test/rails_root/app/models/activity.rb
|
123
124
|
- test/rails_root/app/models/invite.rb
|
125
|
+
- test/rails_root/app/models/invitee.rb
|
124
126
|
- test/rails_root/app/models/user.rb
|
125
127
|
- test/rails_root/app/models/user_session.rb
|
126
128
|
- test/rails_root/app/views/default/index.html.erb
|
@@ -149,6 +151,7 @@ files:
|
|
149
151
|
- test/rails_root/db/migrate/20090703055724_add_contents.rb
|
150
152
|
- test/rails_root/db/migrate/20090704220055_create_slugs.rb
|
151
153
|
- test/rails_root/db/migrate/20090928213532_create_invites.rb
|
154
|
+
- test/rails_root/db/migrate/20091128170318_make_invites_polymorphic.rb
|
152
155
|
- test/rails_root/features/comments.feature
|
153
156
|
- test/rails_root/features/step_definitions/comment_steps.rb
|
154
157
|
- test/rails_root/features/step_definitions/common_steps.rb
|
@@ -356,6 +359,7 @@ files:
|
|
356
359
|
- test/rails_root/test/unit/contacts_test.rb
|
357
360
|
- test/rails_root/test/unit/invite_mailer_test.rb
|
358
361
|
- test/rails_root/test/unit/invite_test.rb
|
362
|
+
- test/rails_root/test/unit/invitee_test.rb
|
359
363
|
- test/rails_root/test/unit/user_test.rb
|
360
364
|
- test/rails_root/vendor/plugins/jrails/CHANGELOG
|
361
365
|
- test/rails_root/vendor/plugins/jrails/LICENSE
|
@@ -411,6 +415,7 @@ test_files:
|
|
411
415
|
- test/rails_root/app/helpers/application_helper.rb
|
412
416
|
- test/rails_root/app/models/activity.rb
|
413
417
|
- test/rails_root/app/models/invite.rb
|
418
|
+
- test/rails_root/app/models/invitee.rb
|
414
419
|
- test/rails_root/app/models/user.rb
|
415
420
|
- test/rails_root/app/models/user_session.rb
|
416
421
|
- test/rails_root/config/boot.rb
|
@@ -434,6 +439,7 @@ test_files:
|
|
434
439
|
- test/rails_root/db/migrate/20090703055724_add_contents.rb
|
435
440
|
- test/rails_root/db/migrate/20090704220055_create_slugs.rb
|
436
441
|
- test/rails_root/db/migrate/20090928213532_create_invites.rb
|
442
|
+
- test/rails_root/db/migrate/20091128170318_make_invites_polymorphic.rb
|
437
443
|
- test/rails_root/features/step_definitions/comment_steps.rb
|
438
444
|
- test/rails_root/features/step_definitions/common_steps.rb
|
439
445
|
- test/rails_root/features/step_definitions/webrat_steps.rb
|
@@ -446,6 +452,7 @@ test_files:
|
|
446
452
|
- test/rails_root/test/unit/contacts_test.rb
|
447
453
|
- test/rails_root/test/unit/invite_mailer_test.rb
|
448
454
|
- test/rails_root/test/unit/invite_test.rb
|
455
|
+
- test/rails_root/test/unit/invitee_test.rb
|
449
456
|
- test/rails_root/test/unit/user_test.rb
|
450
457
|
- test/rails_root/vendor/plugins/jrails/init.rb
|
451
458
|
- test/rails_root/vendor/plugins/jrails/install.rb
|