muck-invites 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|