aitor-tog_social 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/app/models/friendship.rb +112 -0
- data/app/models/group.rb +97 -0
- data/app/models/membership.rb +25 -0
- data/app/models/profile.rb +117 -0
- data/app/models/user.rb +18 -0
- data/config/routes.rb +4 -0
- data/db/migrate/001_create_tog_social_tables.rb +54 -0
- data/test/factories.rb +16 -0
- data/test/test_helper.rb +24 -0
- data/test/unit/group_test.rb +50 -0
- data/test/unit/profile_test.rb +78 -0
- metadata +77 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
# Friendship objects represents the relation between two different members of the social network. The cardinality of the relationship is based on "inviter" and "invited" fields
|
2
|
+
# that store who started the relationship and who is the _passive_ subject of the relationship.
|
3
|
+
#
|
4
|
+
# If you have two profiles, tom and jerry, the following combinations can take place:
|
5
|
+
#
|
6
|
+
# inviter invited status
|
7
|
+
# ------- ------- -------
|
8
|
+
# tom jerry pending tom is a follower of jerry OR jerry is followed by tom OR jerry is a 'following' of tom
|
9
|
+
# jerry tom pending jerry is a follower of tom OR tom is followed by jerry OR tom is a 'following' of jerry
|
10
|
+
#
|
11
|
+
# jerry tom accept | | jerry "begun" the friendship
|
12
|
+
# or | jerry and tom are friends |
|
13
|
+
# jerry tom accept | | tom "begun" the friendship
|
14
|
+
class Friendship < ActiveRecord::Base
|
15
|
+
belongs_to :inviter, :class_name => 'Profile'
|
16
|
+
belongs_to :invited, :class_name => 'Profile'
|
17
|
+
|
18
|
+
PENDING = 0
|
19
|
+
ACCEPTED = 1
|
20
|
+
|
21
|
+
def validate
|
22
|
+
errors.add('inviter', 'inviter and invited can not be the same user') if invited == inviter
|
23
|
+
end
|
24
|
+
class << self
|
25
|
+
|
26
|
+
# Create a new follower of the +inviter+ user. Returns boolean value indicating if the relationship
|
27
|
+
# correctly created.
|
28
|
+
#
|
29
|
+
# ==== Options
|
30
|
+
#
|
31
|
+
# +inviter+ +Profile+ if the person that wants to be a follower if +invited+
|
32
|
+
#
|
33
|
+
# +invited+ +Profile+ of the user followed by +inviter+
|
34
|
+
#
|
35
|
+
def add_follower(inviter, invited)
|
36
|
+
a = Friendship.create(:inviter => inviter, :invited => invited, :status => PENDING)
|
37
|
+
!a.new_record?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create a friendship between the user and the target. Returns boolean value indicating if
|
41
|
+
# the relationship was correctly created.
|
42
|
+
#
|
43
|
+
# ==== Options
|
44
|
+
#
|
45
|
+
# +user+ +Profile+ or +User+ that purpose the friendship
|
46
|
+
#
|
47
|
+
# +target+ +Profile+ or +User+ that receives the purposement relationship
|
48
|
+
#
|
49
|
+
def make_friends(user, target)
|
50
|
+
transaction do
|
51
|
+
user = profile_of(user)
|
52
|
+
target = profile_of(target)
|
53
|
+
begin
|
54
|
+
find_friendship(user, target, PENDING).update_attribute(:status, ACCEPTED)
|
55
|
+
Friendship.create!(:inviter_id => target.id, :invited_id => user.id, :status => ACCEPTED)
|
56
|
+
rescue Exception
|
57
|
+
return make_friends(target, user) if user.followed_by? target
|
58
|
+
return add_follower(user, target)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def stop_being_friends(user, target)
|
65
|
+
transaction do
|
66
|
+
begin
|
67
|
+
find_friendship(target, user, ACCEPTED).update_attribute(:status, PENDING)
|
68
|
+
find_friendship(user, target, ACCEPTED).destroy
|
69
|
+
rescue Exception
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset(user, target)
|
77
|
+
begin
|
78
|
+
find_friendship(user, target).destroy
|
79
|
+
find_friendship(target, user, ACCEPTED).update_attribute(:status, PENDING)
|
80
|
+
rescue Exception
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def find_friendship(inviter, invited, status)
|
89
|
+
conditions = {:inviter_id => inviter.id, :invited_id => invited.id}
|
90
|
+
conditions.merge!(:status => status) if status
|
91
|
+
Friendship.find(:first, :conditions => conditions)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def accept!
|
97
|
+
self.update_attribute(:status, ACCEPTED)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def profile_of(user)
|
102
|
+
profile = case user
|
103
|
+
when User
|
104
|
+
user.profile
|
105
|
+
when Profile
|
106
|
+
user
|
107
|
+
else
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
data/app/models/group.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
class Group < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :author, :class_name => 'User', :foreign_key => 'user_id'
|
4
|
+
|
5
|
+
has_many :memberships
|
6
|
+
|
7
|
+
has_many :moderator_memberships, :class_name => 'Membership',
|
8
|
+
:conditions => ['memberships.moderator = ?', true]
|
9
|
+
|
10
|
+
has_many :members, :through => :memberships, :source => :user,
|
11
|
+
:conditions => ['memberships.state = ?', 'active']
|
12
|
+
|
13
|
+
has_many :pending_members, :through => :memberships, :source => :user,
|
14
|
+
:conditions => ['memberships.state = ?', 'pending']
|
15
|
+
|
16
|
+
has_many :moderators, :through => :moderator_memberships, :source => :user,
|
17
|
+
:conditions => ['memberships.state = ?', 'active']
|
18
|
+
|
19
|
+
|
20
|
+
#file_column :image, :root_path => File.join(RAILS_ROOT, "public/system/group_photos"), :web_root => 'system/group_photos/', :magick => {
|
21
|
+
# :versions => {
|
22
|
+
# :big => {:crop => "1:1", :size => Tog::Config["system.group.image.versions.big"], :name => "big"},
|
23
|
+
# :medium => {:crop => "1:1", :size => Tog::Config["system.group.image.versions.medium"], :name => "medium"},
|
24
|
+
# :small => {:crop => "1:1", :size => Tog::Config["system.group.image.versions.small"], :name => "small" },
|
25
|
+
# :tiny => {:crop => "1:1", :size => Tog::Config["system.group.image.versions.tiny"], :name => "tiny" }
|
26
|
+
# }
|
27
|
+
#}
|
28
|
+
|
29
|
+
acts_as_state_machine :initial => :pending
|
30
|
+
state :pending, :enter => :make_activation_code
|
31
|
+
state :active, :enter => :do_activate
|
32
|
+
event :activate do
|
33
|
+
transitions :from => :pending, :to => :active
|
34
|
+
end
|
35
|
+
|
36
|
+
validates_uniqueness_of :name
|
37
|
+
validates_presence_of :name
|
38
|
+
validates_presence_of :author
|
39
|
+
|
40
|
+
def membership_of(user)
|
41
|
+
mem = memberships.select{|m| m.user == user}
|
42
|
+
return mem.first unless mem.blank?
|
43
|
+
end
|
44
|
+
|
45
|
+
def activate_membership(user)
|
46
|
+
mem = membership_of(user)
|
47
|
+
mem.activate! if mem && mem.pending?
|
48
|
+
end
|
49
|
+
|
50
|
+
def grant_moderator(user)
|
51
|
+
moderator_privileges(user,true)
|
52
|
+
end
|
53
|
+
|
54
|
+
def revoke_moderator(user)
|
55
|
+
moderator_privileges(user,false)
|
56
|
+
end
|
57
|
+
|
58
|
+
def moderator_privileges(user, grant=false)
|
59
|
+
mem = membership_of(user)
|
60
|
+
mem.moderator = grant
|
61
|
+
mem.save!
|
62
|
+
end
|
63
|
+
|
64
|
+
def join(user,moderator=false)
|
65
|
+
# todo Confirm what to do if th user is already a member. By now just ignore it and continue.
|
66
|
+
mem = membership_of(user)
|
67
|
+
mem = self.memberships.build(:user => user) unless mem
|
68
|
+
mem.save!
|
69
|
+
mem.activate! unless self.moderated?
|
70
|
+
end
|
71
|
+
|
72
|
+
def leave(user)
|
73
|
+
mem = membership_of(user)
|
74
|
+
mem.destroy if mem
|
75
|
+
end
|
76
|
+
|
77
|
+
def is_banned(user)
|
78
|
+
raise "Implement this..."
|
79
|
+
end
|
80
|
+
|
81
|
+
def ban(user)
|
82
|
+
raise "Implement this..."
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
protected
|
87
|
+
def make_activation_code
|
88
|
+
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
89
|
+
end
|
90
|
+
|
91
|
+
def do_activate
|
92
|
+
self.activated_at = Time.now.utc
|
93
|
+
self.activation_code = nil
|
94
|
+
self.moderator_memberships.each{|mod| mod.activate!}
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Membership < ActiveRecord::Base
|
2
|
+
belongs_to :group
|
3
|
+
belongs_to :user
|
4
|
+
|
5
|
+
acts_as_state_machine :initial => :pending
|
6
|
+
|
7
|
+
state :pending, :enter => :make_activation_code
|
8
|
+
state :active, :enter => :do_activate
|
9
|
+
|
10
|
+
event :activate do
|
11
|
+
transitions :from => :pending, :to => :active
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def make_activation_code
|
17
|
+
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_activate
|
21
|
+
self.activated_at = Time.now.utc
|
22
|
+
self.activation_code = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
class Profile < ActiveRecord::Base
|
2
|
+
belongs_to :user
|
3
|
+
|
4
|
+
#file_column :icon, :root_path => File.join(RAILS_ROOT, "public/system/profile"), :web_root => 'system/profile/', :magick => {
|
5
|
+
# :versions => {
|
6
|
+
# :big => {:crop => "1:1", :size => Tog::Config["system.profile.image.versions.big"], :name => "big"},
|
7
|
+
# :medium => {:crop => "1:1", :size => Tog::Config["system.profile.image.versions.medium"], :name => "medium"},
|
8
|
+
# :small => {:crop => "1:1", :size => Tog::Config["system.profile.image.versions.small"], :name => "small"},
|
9
|
+
# :tiny => {:crop => "1:1", :size => Tog::Config["system.profile.image.versions.tiny"], :name => "tiny"}
|
10
|
+
# }
|
11
|
+
#}
|
12
|
+
|
13
|
+
has_many :friendships_by_others, :class_name => "Friendship", :foreign_key => 'invited_id', :conditions => "status = #{Friendship::ACCEPTED}"
|
14
|
+
has_many :friendships_by_me, :class_name => "Friendship", :foreign_key => 'inviter_id', :conditions => "status = #{Friendship::ACCEPTED}"
|
15
|
+
|
16
|
+
has_many :follower_friendships, :class_name => "Friendship", :foreign_key => "invited_id", :conditions => "status = #{Friendship::PENDING}"
|
17
|
+
has_many :following_friendships, :class_name => "Friendship", :foreign_key => "inviter_id", :conditions => "status = #{Friendship::PENDING}"
|
18
|
+
|
19
|
+
has_many :friends_by_others, :through => :friendships_by_others, :source => :inviter
|
20
|
+
has_many :friends_by_me, :through => :friendships_by_me, :source => :invited
|
21
|
+
|
22
|
+
has_many :followers, :through => :follower_friendships, :source => :inviter
|
23
|
+
has_many :followings, :through => :following_friendships, :source => :invited
|
24
|
+
|
25
|
+
before_create :set_default_icon
|
26
|
+
|
27
|
+
|
28
|
+
def friends
|
29
|
+
# Reload associations just to make sure we're working with the current staff. Bad smell!
|
30
|
+
# todo check this... if we don't should reload the relationship to get the test working...
|
31
|
+
(friends_by_others(true) + friends_by_me(true)).uniq
|
32
|
+
end
|
33
|
+
def friendships
|
34
|
+
(friendships_by_others(true) + friendships_by_me(true)).uniq
|
35
|
+
end
|
36
|
+
|
37
|
+
def full_name
|
38
|
+
#todo apply for internationalization
|
39
|
+
first_name.blank? && last_name.blank? ? self.user.login : "#{first_name} #{last_name}".strip
|
40
|
+
end
|
41
|
+
|
42
|
+
def followed_by? profile
|
43
|
+
followers(true).include? profile
|
44
|
+
end
|
45
|
+
|
46
|
+
def follows? profile
|
47
|
+
followings(true).include? profile
|
48
|
+
end
|
49
|
+
def is_friend_of? profile
|
50
|
+
friends.include? profile
|
51
|
+
end
|
52
|
+
def is_related_to? profile
|
53
|
+
me.followed_by?(profile) || me.follows?(profile) || me.is_friend_of?(profile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_follower(follower)
|
57
|
+
if follower.follows? me
|
58
|
+
return false
|
59
|
+
elsif me.follows? follower
|
60
|
+
return add_friend(follower)
|
61
|
+
else
|
62
|
+
flw = Friendship.create(:inviter => follower, :invited => me, :status => Friendship::PENDING)
|
63
|
+
unless flw.new_record?
|
64
|
+
# todo enable send_friendships_notifications? setting per profile
|
65
|
+
# FriendshipMailer.deliver_new_follower(me, follower) if me.send_friendships_notifications?
|
66
|
+
FriendshipMailer.deliver_new_follower(me, follower)
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_following(following)
|
74
|
+
following.add_follower(me)
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_friend(friend)
|
78
|
+
relationship = if friend.follows? me
|
79
|
+
find_friendship(friend, me, Friendship::PENDING)
|
80
|
+
elsif friend.followed_by? me
|
81
|
+
find_friendship(me, friend, Friendship::PENDING)
|
82
|
+
else
|
83
|
+
Friendship.create(:inviter => friend, :invited => me, :status => Friendship::PENDING)
|
84
|
+
end
|
85
|
+
relationship.accept!
|
86
|
+
# todo enable send_friendships_notifications? setting per profile
|
87
|
+
# FriendshipMailer.deliver_frienship_validated(relationship.inviter, relationship.invited) if relationship.inviter.send_friendships_notifications?
|
88
|
+
FriendshipMailer.deliver_friendship_validated(relationship.inviter, relationship.invited)
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
def remove_friend(friend)
|
92
|
+
relationships = me.friendships.select{|f| f.inviter == friend || f.invited == friend }
|
93
|
+
relationships.each{|r| r.destroy}
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
private
|
98
|
+
# Freud will be happy.
|
99
|
+
def me
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_friendship(inviter, invited, status)
|
104
|
+
conditions = {:inviter_id => inviter.id, :invited_id => invited.id}
|
105
|
+
conditions.merge!(:status => status) if status
|
106
|
+
Friendship.find(:first, :conditions => conditions)
|
107
|
+
end
|
108
|
+
def set_default_icon
|
109
|
+
unless self.icon
|
110
|
+
if Tog::Config["system.profile.image.default"]
|
111
|
+
default_profile_icon = File.join(RAILS_ROOT, 'public', 'images', Tog::Config["system.profile.image.default"])
|
112
|
+
self.icon = File.new(default_profile_icon)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
|
3
|
+
has_one :profile, :dependent => :destroy
|
4
|
+
has_many :memberships
|
5
|
+
has_many :moderator_memberships, :class_name => 'Membership',
|
6
|
+
:conditions => ['memberships.moderator = ?', true]
|
7
|
+
|
8
|
+
has_many :groups, :through => :memberships,
|
9
|
+
:conditions => "memberships.state='active' and groups.state='active'"
|
10
|
+
|
11
|
+
has_many :moderated_groups, :through => :moderator_memberships,
|
12
|
+
:conditions => "memberships.state='active' and groups.state='active'", :source => :group
|
13
|
+
|
14
|
+
def name
|
15
|
+
profile.full_name
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class CreateTogSocialTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :profiles do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.string :first_name
|
6
|
+
t.string :last_name
|
7
|
+
t.string :website
|
8
|
+
t.string :blog
|
9
|
+
t.string :icon
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
User.find(:all).each{|u|
|
13
|
+
profile = Profile.new
|
14
|
+
profile.user = u
|
15
|
+
profile.save!
|
16
|
+
}
|
17
|
+
|
18
|
+
create_table :groups do |t|
|
19
|
+
t.string :name
|
20
|
+
t.string :description
|
21
|
+
t.string :image
|
22
|
+
t.string :state
|
23
|
+
t.boolean :private
|
24
|
+
t.boolean :moderated, :default => true
|
25
|
+
t.integer :user_id
|
26
|
+
t.string :activation_code, :limit => 40
|
27
|
+
t.datetime :activated_at
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :memberships do |t|
|
32
|
+
t.integer :user_id
|
33
|
+
t.integer :group_id
|
34
|
+
t.boolean :moderator
|
35
|
+
t.string :state
|
36
|
+
t.string :activation_code, :limit => 40
|
37
|
+
t.datetime :activated_at
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
create_table :friendships do |t|
|
41
|
+
t.integer :inviter_id
|
42
|
+
t.integer :invited_id
|
43
|
+
t.integer :status
|
44
|
+
t.timestamps
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.down
|
49
|
+
drop_table :friendships
|
50
|
+
drop_table :memberships
|
51
|
+
drop_table :groups
|
52
|
+
drop_table :profiles
|
53
|
+
end
|
54
|
+
end
|
data/test/factories.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Factory.define :user do |u|
|
2
|
+
u.salt '7e3041ebc2fc05a40c60028e2c4901a81035d3cd'
|
3
|
+
u.crypted_password '00742970dc9e6319f8019fd54864d3ea740f04b1'
|
4
|
+
u.activation_code '8f24789ae988411ccf33ab0c30fe9106fab32e9a'
|
5
|
+
u.state 'pending'
|
6
|
+
u.email {|a| "#{a.login}@example.com".downcase }
|
7
|
+
end
|
8
|
+
|
9
|
+
Factory.define :profile do |u|
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
Factory.define :group do |g|
|
14
|
+
g.state 'active'
|
15
|
+
#g.author{|author| author.association :user, :login => 'chavez'}
|
16
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
|
3
|
+
require 'test_help'
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
require 'factory_girl'
|
7
|
+
require File.expand_path(File.dirname(__FILE__) + '/factories')
|
8
|
+
|
9
|
+
class Test::Unit::TestCase
|
10
|
+
self.use_transactional_fixtures = true
|
11
|
+
self.use_instantiated_fixtures = false
|
12
|
+
fixtures :all
|
13
|
+
|
14
|
+
def assert_difference(object, method = nil, difference = 1)
|
15
|
+
initial_value = object.send(method)
|
16
|
+
yield
|
17
|
+
assert_equal initial_value + difference, object.send(method), "#{object}##{method} should have a difference of #{difference}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def assert_no_difference(object, method, &block)
|
21
|
+
assert_difference object, method, 0, &block
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class GroupTest < Test::Unit::TestCase
|
4
|
+
context "A Group" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@berlusconi = Factory(:user, :login => 'berlusconi')
|
8
|
+
@chavez = Factory(:user, :login => 'chavez')
|
9
|
+
@pornfans = Factory(:group, :name => 'Porn without frontiers', :moderated => false, :author => @chavez)
|
10
|
+
end
|
11
|
+
|
12
|
+
should "should allow to join directly" do
|
13
|
+
@pornfans.join(@berlusconi)
|
14
|
+
assert @pornfans.members.include?(@berlusconi), "The joined user should be on the members list"
|
15
|
+
end
|
16
|
+
|
17
|
+
should "allow give moderator rights" do
|
18
|
+
@pornfans.join(@berlusconi)
|
19
|
+
assert_no_difference(Membership, :count) do
|
20
|
+
@pornfans.grant_moderator(@berlusconi)
|
21
|
+
end
|
22
|
+
assert_contains @pornfans.moderators, @berlusconi
|
23
|
+
end
|
24
|
+
|
25
|
+
should "allow revoke moderator rights" do
|
26
|
+
@pornfans.join(@berlusconi)
|
27
|
+
assert_no_difference(Membership, :count) do
|
28
|
+
@pornfans.revoke_moderator(@berlusconi)
|
29
|
+
end
|
30
|
+
assert_does_not_contain @pornfans.moderators, @berlusconi
|
31
|
+
end
|
32
|
+
|
33
|
+
context "that is moderated" do
|
34
|
+
setup do
|
35
|
+
@selectedporn = Factory(:group, :name => 'Porn for V.I.P', :moderated => true, :author => @chavez)
|
36
|
+
end
|
37
|
+
|
38
|
+
should "not allow to join directly" do
|
39
|
+
assert_difference(Membership, :count) do
|
40
|
+
@selectedporn.join(@berlusconi)
|
41
|
+
end
|
42
|
+
assert !@selectedporn.members.include?(@berlusconi)
|
43
|
+
@selectedporn.activate_membership(@berlusconi)
|
44
|
+
assert @selectedporn.members(true).include?(@berlusconi)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class ProfileTest < Test::Unit::TestCase
|
4
|
+
context "A Profile " do
|
5
|
+
setup do
|
6
|
+
@user = Factory(:user, :login => 'chavez')
|
7
|
+
@user2 = Factory(:user, :login => 'evo')
|
8
|
+
|
9
|
+
@chavez = Factory(:profile, :first_name => 'Hugo', :last_name => 'Chavez', :user => @user)
|
10
|
+
@evo = Factory(:profile, :first_name => 'Evo', :last_name => 'Morales', :user => @user2)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "returna full_name correctly base on first_name and last_name" do
|
14
|
+
assert_equal "Hugo Chavez", @chavez.full_name, "Full name should Hugo Chavez"
|
15
|
+
end
|
16
|
+
|
17
|
+
should "return last_name as full_name if first_name is blank" do
|
18
|
+
[nil, ""].each {|value|
|
19
|
+
@chavez.first_name = value
|
20
|
+
assert_equal "Chavez", @chavez.full_name, "Full name should Chavez if first name is blank"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
should "return login as full_name if first name and last name are blank" do
|
24
|
+
[nil, ""].each {|value|
|
25
|
+
@chavez.first_name = @chavez.last_name = value
|
26
|
+
assert_equal "chavez", @chavez.full_name, "full_name should defaults to login if first name and last name are blank"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
should "allow to add a follower" do
|
31
|
+
@chavez.add_follower(@evo)
|
32
|
+
assert @evo.follows?(@chavez), "Evo should follow Chavez"
|
33
|
+
assert @chavez.followed_by?(@evo), "Chavez should be followed by Evo"
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def test_add_following
|
38
|
+
@evo.add_following(@chavez)
|
39
|
+
assert @evo.follows?(@chavez), "Evo should follow Chavez"
|
40
|
+
assert @chavez.followed_by?(@evo), "Chavez should be followed by Evo"
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_add_follower_twice_has_no_effect
|
44
|
+
assert_difference(Friendship, :count) do
|
45
|
+
@chavez.add_follower(@evo)
|
46
|
+
end
|
47
|
+
assert_no_difference(Friendship, :count) do
|
48
|
+
@chavez.add_follower(@evo)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def test_add_follower_from_a_person_im_following_should_convert_the_relationship_on_a_friendship
|
54
|
+
@chavez.add_follower(@evo)
|
55
|
+
@evo.add_follower(@chavez)
|
56
|
+
assert @evo.is_friend_of?(@chavez)
|
57
|
+
assert @chavez.is_friend_of?(@evo)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_add_friend
|
61
|
+
assert !@evo.is_related_to?(@chavez)
|
62
|
+
assert @evo.add_friend(@chavez)
|
63
|
+
assert @evo.is_friend_of?(@chavez), "Evo and Chavez should be friends"
|
64
|
+
assert @chavez.is_friend_of?(@evo), "Chavez and Evo should be friends"
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_remove_friend
|
68
|
+
assert @evo.add_friend(@chavez)
|
69
|
+
assert @evo.is_friend_of?(@chavez), "Evo and Chavez should be friends"
|
70
|
+
@evo.remove_friend(@chavez)
|
71
|
+
assert !@evo.is_friend_of?(@chavez)
|
72
|
+
assert !@evo.is_related_to?(@chavez)
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aitor-tog_social
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aitor Garcia
|
8
|
+
- Roberto Salicio
|
9
|
+
- Alberto Molpeceres
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2008-04-24 00:00:00 -07:00
|
15
|
+
default_executable:
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: mime-types
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
description: Tog social
|
27
|
+
email: aitor@linkingpaths
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- app/helpers
|
36
|
+
- app/models/friendship.rb
|
37
|
+
- app/models/group.rb
|
38
|
+
- app/models/membership.rb
|
39
|
+
- app/models/profile.rb
|
40
|
+
- app/models/user.rb
|
41
|
+
- app/views
|
42
|
+
- config/routes.rb
|
43
|
+
- db/migrate/001_create_tog_social_tables.rb
|
44
|
+
- tasks
|
45
|
+
- test/factories.rb
|
46
|
+
- test/test_helper.rb
|
47
|
+
- test/unit/group_test.rb
|
48
|
+
- test/unit/profile_test.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/aitor/tog_social
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --main
|
54
|
+
- README.txt
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.2.0
|
73
|
+
signing_key:
|
74
|
+
specification_version: 2
|
75
|
+
summary: tog_social
|
76
|
+
test_files: []
|
77
|
+
|