aitor-tog_social 0.1
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/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
|
+
|