redu-has_friends 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.mkd +5 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +137 -0
- data/Rakefile +11 -0
- data/has_friends.gemspec +29 -0
- data/lib/friendship.rb +55 -0
- data/lib/has_friends.rb +114 -0
- data/lib/version.rb +3 -0
- data/spec/has_friends_spec.rb +256 -0
- data/spec/schema.rb +23 -0
- data/spec/spec_helper.rb +22 -0
- metadata +182 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.mkd
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Nando Vieira
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/redu/has_friends.png?branch=master)](https://travis-ci.org/redu/has_friends)
|
2
|
+
|
3
|
+
Instalation
|
4
|
+
-----------
|
5
|
+
|
6
|
+
### Requirements
|
7
|
+
|
8
|
+
This gem requires at least Ruby 1.9.3 and Rails 3.2+.
|
9
|
+
|
10
|
+
Install in the Gemfile
|
11
|
+
|
12
|
+
gem redu-has_friends, '~> 1.0'
|
13
|
+
|
14
|
+
Then generate a migration with `script/generate migration create_friendships` and add the following code:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
class CreateFriendships < ActiveRecord::Migration
|
18
|
+
def self.up
|
19
|
+
create_table :friendships do |t|
|
20
|
+
t.references :user, :friend
|
21
|
+
t.string :status
|
22
|
+
t.datetime :requested_at, :null => false
|
23
|
+
t.datetime :accepted_at, :null => true, :default => nil
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index :friendships, :user_id
|
27
|
+
add_index :friendships, :friend_id
|
28
|
+
add_index :friendships, :status
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.down
|
32
|
+
drop_table :friendships
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Finally, run the migrations with `rake db:migrate`
|
38
|
+
|
39
|
+
Usage
|
40
|
+
-----
|
41
|
+
|
42
|
+
Add the method call `has_friends` to your model.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class User < ActiveRecord::Base
|
46
|
+
has_friends
|
47
|
+
end
|
48
|
+
|
49
|
+
john = User.find_by_login 'john'
|
50
|
+
mary = User.find_by_login 'mary'
|
51
|
+
paul = User.find_by_login 'paul'
|
52
|
+
|
53
|
+
# john wants to be friend with mary
|
54
|
+
# always return a friendship object
|
55
|
+
john.be_friends_with(mary)
|
56
|
+
|
57
|
+
# are they friends?
|
58
|
+
john.friends?(mary)
|
59
|
+
|
60
|
+
# get the friendship object
|
61
|
+
john.friendship_for(mary)
|
62
|
+
|
63
|
+
# mary accepts john's request if it exists;
|
64
|
+
# makes a friendship request otherwise.
|
65
|
+
mary.be_friends_with(john)
|
66
|
+
|
67
|
+
# check if paul is mary's friend
|
68
|
+
mary.friends?(paul)
|
69
|
+
|
70
|
+
# check if an user is the current user, so it can
|
71
|
+
# be differently presented
|
72
|
+
mary.friends.each {|friend| friend.is?(current_user) }
|
73
|
+
|
74
|
+
# if you're dealing with a friendship object,
|
75
|
+
# the following methods are available
|
76
|
+
friendship.accept!
|
77
|
+
|
78
|
+
# if you're using has_paginate plugin, you can use it:
|
79
|
+
mary.friends.paginate(:page => 3, :limit => 10)
|
80
|
+
|
81
|
+
# the be_friends_with method returns 2 params: friendship object and status.
|
82
|
+
# the friendship object will be present only when the friendship is created
|
83
|
+
# (that is, when is requested for the first time)
|
84
|
+
# STATUS_ALREADY_FRIENDS # => users are already friends
|
85
|
+
# STATUS_ALREADY_REQUESTED # => user has already requested friendship
|
86
|
+
# STATUS_IS_YOU # => user is trying add himself as friend
|
87
|
+
# STATUS_FRIEND_IS_REQUIRED # => friend argument is missing
|
88
|
+
# STATUS_FRIENDSHIP_ACCEPTED # => friendship has been accepted
|
89
|
+
# STATUS_REQUESTED # => friendship has been requested
|
90
|
+
|
91
|
+
friendship, status = mary.be_friends_with(john)
|
92
|
+
|
93
|
+
if status == Friends::STATUS_REQUESTED
|
94
|
+
# the friendship has been requested
|
95
|
+
Mailer.deliver_friendship_request(friendship)
|
96
|
+
elsif status == Friends::STATUS_ALREADY_FRIENDS
|
97
|
+
# they're already friends
|
98
|
+
else
|
99
|
+
# ...
|
100
|
+
end
|
101
|
+
|
102
|
+
NOTE: You should have a User model. You should also have a `friends_count` column
|
103
|
+
on your model. Otherwise, this won't work! Create a new migration with `script/generate migration add_friends_count_to_user`:
|
104
|
+
|
105
|
+
class AddFriendsCountToUser < ActiveRecord::Migration
|
106
|
+
def self.up
|
107
|
+
add_column :users, :friends_count, :integer, :default => 0, :null => false
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.down
|
111
|
+
remove_column :users, :friends_count
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
1. Fork it
|
119
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
120
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
121
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
122
|
+
5. Create new Pull Request
|
123
|
+
|
124
|
+
|
125
|
+
<img src="https://github.com/downloads/redu/redupy/redutech-marca.png" alt="Redu Educational Technologies" width="300">
|
126
|
+
|
127
|
+
This project is maintained and funded by [Redu Educational Techologies](http://tech.redu.com.br).
|
128
|
+
|
129
|
+
# Copyright
|
130
|
+
|
131
|
+
Copyright (c) 2012 Redu Educational Technologies
|
132
|
+
|
133
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
134
|
+
|
135
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
136
|
+
|
137
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE..
|
data/Rakefile
ADDED
data/has_friends.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "redu-has_friends"
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.version = Friends::VERSION
|
9
|
+
s.authors = ["jessicabarbalho, guiocavalcanti"]
|
10
|
+
s.email = ["jessica@redu.com.br", "guilhermec@redu.com.br"]
|
11
|
+
s.homepage = "https://github.com/redu/has_friends"
|
12
|
+
s.summary = %q{Adiciona suporte a amizado numa aplicação rails}
|
13
|
+
s.description = %q{Permite que o usuário se relacione com outros usuários dentro de uma aplicação rails por meio de amizades}
|
14
|
+
|
15
|
+
s.rubyforge_project = "has_friends"
|
16
|
+
s.add_development_dependency 'rspec'
|
17
|
+
s.add_development_dependency 'rake'
|
18
|
+
s.add_development_dependency 'bundler'
|
19
|
+
s.add_development_dependency 'activerecord', '~> 3.2'
|
20
|
+
s.add_development_dependency 'sqlite3'
|
21
|
+
s.add_development_dependency 'shoulda-matchers'
|
22
|
+
s.add_development_dependency 'debugger'
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
end
|
29
|
+
|
data/lib/friendship.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
class Friendship < ActiveRecord::Base
|
2
|
+
# constants
|
3
|
+
STATUS_ALREADY_FRIENDS = 1
|
4
|
+
STATUS_ALREADY_REQUESTED = 2
|
5
|
+
STATUS_IS_YOU = 3
|
6
|
+
STATUS_FRIEND_IS_REQUIRED = 4
|
7
|
+
STATUS_FRIENDSHIP_ACCEPTED = 5
|
8
|
+
STATUS_REQUESTED = 6
|
9
|
+
|
10
|
+
# associations
|
11
|
+
belongs_to :user
|
12
|
+
belongs_to :friend, :class_name => 'User', :foreign_key => 'friend_id'
|
13
|
+
|
14
|
+
# callback
|
15
|
+
after_destroy do |f|
|
16
|
+
user = User.find(f.user_id)
|
17
|
+
unless user.friends_count == 0
|
18
|
+
User.decrement_counter(:friends_count, f.user_id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
before_create do |f|
|
23
|
+
f.requested_at = Time.now
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.pending
|
27
|
+
where(:status => 'pending')
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.accepted
|
31
|
+
where(:status => 'accepted')
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.requested
|
35
|
+
where(:status => 'requested')
|
36
|
+
end
|
37
|
+
|
38
|
+
def pending?
|
39
|
+
status == 'pending'
|
40
|
+
end
|
41
|
+
|
42
|
+
def accepted?
|
43
|
+
status == 'accepted'
|
44
|
+
end
|
45
|
+
|
46
|
+
def requested?
|
47
|
+
status == 'requested'
|
48
|
+
end
|
49
|
+
|
50
|
+
def accept!
|
51
|
+
User.increment_counter(:friends_count, user_id) unless accepted?
|
52
|
+
update_attribute(:status, 'accepted')
|
53
|
+
touch(:accepted_at)
|
54
|
+
end
|
55
|
+
end
|
data/lib/has_friends.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'friendship'
|
2
|
+
|
3
|
+
module Friends
|
4
|
+
def self.included(base)
|
5
|
+
base.extend Friends::ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def has_friends
|
10
|
+
include Friends::InstanceMethods
|
11
|
+
|
12
|
+
has_many :friendships, :class_name => 'Friendship'
|
13
|
+
has_many :friends, :through => :friendships, :source => :friend, :conditions => "friendships.status = 'accepted'"
|
14
|
+
has_many :friends_pending, :through => :friendships, :source => :friend, :conditions => "friendships.status = 'pending'"
|
15
|
+
|
16
|
+
before_destroy :destroy_all_friendships
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
def be_friends_with(friend)
|
22
|
+
# no user object
|
23
|
+
return nil, Friendship::STATUS_FRIEND_IS_REQUIRED unless friend
|
24
|
+
|
25
|
+
# should not create friendship if user is trying to add himself
|
26
|
+
return nil, Friendship::STATUS_IS_YOU if is?(friend)
|
27
|
+
|
28
|
+
# should not create friendship if users are already friends
|
29
|
+
return nil, Friendship::STATUS_ALREADY_FRIENDS if friends?(friend)
|
30
|
+
|
31
|
+
# retrieve the friendship request
|
32
|
+
friendship = self.friendship_for(friend)
|
33
|
+
|
34
|
+
# let's check if user has already a friendship request or have removed
|
35
|
+
request = friend.friendship_for(self)
|
36
|
+
|
37
|
+
# friendship has already been requested
|
38
|
+
return nil, Friendship::STATUS_ALREADY_REQUESTED if friendship && friendship.requested?
|
39
|
+
|
40
|
+
# friendship is pending so accept it
|
41
|
+
if friendship && friendship.pending?
|
42
|
+
friendship.accept!
|
43
|
+
request.accept!
|
44
|
+
|
45
|
+
return friendship, Friendship::STATUS_FRIENDSHIP_ACCEPTED
|
46
|
+
end
|
47
|
+
|
48
|
+
# we didn't find a friendship, so let's create one!
|
49
|
+
friendship = self.friendships.create(:friend_id => friend.id, :status => 'requested')
|
50
|
+
|
51
|
+
# we didn't find a friendship request, so let's create it!
|
52
|
+
request = friend.friendships.create(:friend_id => id, :status => 'pending')
|
53
|
+
|
54
|
+
return friendship, Friendship::STATUS_REQUESTED
|
55
|
+
end
|
56
|
+
|
57
|
+
def friends?(friend)
|
58
|
+
if friends.loaded?
|
59
|
+
friends.include?(friend)
|
60
|
+
else
|
61
|
+
friendship = friendship_for(friend)
|
62
|
+
friendship && friendship.accepted?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def friendship_for(friend)
|
67
|
+
if friendships.loaded?
|
68
|
+
friendships.select{ |friendship| friendship.friend_id == friend.id }.first
|
69
|
+
else
|
70
|
+
friendships.where(:friend_id => friend.id).first
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def is?(friend)
|
75
|
+
self.id == friend.id
|
76
|
+
end
|
77
|
+
|
78
|
+
def friends_in_common_with(user)
|
79
|
+
self.friends & user.friends
|
80
|
+
end
|
81
|
+
|
82
|
+
def friends_not_in_common_with(user)
|
83
|
+
self.friends.where("users.id NOT IN (?)",
|
84
|
+
user.friends.collect(&:id) << user.id)
|
85
|
+
end
|
86
|
+
|
87
|
+
def friends_of_friends
|
88
|
+
friends_ids = self.friends.collect(&:id)
|
89
|
+
fof_ids = Friendship.select("friend_id").
|
90
|
+
where("user_id IN (?)"" AND friend_id NOT IN (?)",
|
91
|
+
friends_ids, friends_ids << self.id)
|
92
|
+
|
93
|
+
User.where("id IN (?)", fof_ids.collect(&:friend_id))
|
94
|
+
end
|
95
|
+
|
96
|
+
# Destroyes (in both ways) the friendship
|
97
|
+
def destroy_friendship_with(friend)
|
98
|
+
friendship = friendship_for(friend)
|
99
|
+
other_friendship = friend.friendship_for(self)
|
100
|
+
friendship.try(:destroy)
|
101
|
+
other_friendship.try(:destroy)
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
# Destroyes all friendships of user
|
107
|
+
def destroy_all_friendships
|
108
|
+
Friendship.destroy_all({:user_id => id})
|
109
|
+
Friendship.destroy_all({:friend_id => id})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
ActiveRecord::Base.send(:include, Friends)
|
data/lib/version.rb
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "ruby-debug"
|
3
|
+
|
4
|
+
# unset models used for testing purposes
|
5
|
+
Object.unset_class('User')
|
6
|
+
|
7
|
+
class User < ActiveRecord::Base
|
8
|
+
has_friends
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "has_friends" do
|
12
|
+
before do
|
13
|
+
User.delete_all
|
14
|
+
|
15
|
+
@vader = User.create(:login => "darth_vader")
|
16
|
+
@luke = User.create(:login => "luke_skywalker")
|
17
|
+
@leia = User.create(:login => "princess_leia")
|
18
|
+
@han_solo = User.create(:login => "han_solo")
|
19
|
+
@yoda = User.create(:login => "yoda")
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "methods" do
|
23
|
+
it "should respond to has_friends method" do
|
24
|
+
User.should respond_to(:has_friends)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should respond to be_friends_with method" do
|
28
|
+
@vader.should respond_to(:be_friends_with)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should respond to friends? method" do
|
32
|
+
@vader.should respond_to(:friends?)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should respond to friends_in_common_with method" do
|
36
|
+
@vader.should respond_to(:friends_in_common_with)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should responde to friends_not_in_common_with" do
|
40
|
+
@vader.should respond_to(:friends_not_in_common_with)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should respond to friends_of_friends method" do
|
44
|
+
@vader.should respond_to(:friends_of_friends)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should respond to destroy_friendship_with" do
|
48
|
+
@vader.should respond_to(:destroy_friendship_with)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "friends" do
|
53
|
+
before(:each) do
|
54
|
+
create_friendship @vader, @luke
|
55
|
+
create_friendship @vader, @leia
|
56
|
+
create_friendship @luke, @leia
|
57
|
+
create_friendship @luke, @yoda
|
58
|
+
create_friendship @leia, @han_solo
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should order vader's friends" do
|
62
|
+
# => princess_leia, luke_skywalker
|
63
|
+
@vader.friends.all(:order => 'login desc').should == [@leia, @luke]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return luke's friends" do
|
67
|
+
@luke.friends.should == [@vader, @leia, @yoda]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return leia's frieds" do
|
71
|
+
@leia.friends.should == [@vader, @luke, @han_solo]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return yoda's friends" do
|
75
|
+
@yoda.friends.should == [@luke]
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return solo's friends" do
|
79
|
+
@han_solo.friends.should == [@leia]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should increment counter" do
|
83
|
+
@vader.reload
|
84
|
+
@vader.friends_count.should == 2
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should decrement counter" do
|
88
|
+
friendship = @vader.friendship_for(@luke)
|
89
|
+
friendship.destroy
|
90
|
+
|
91
|
+
@vader.reload
|
92
|
+
@vader.friends_count.should == 1
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should be @vader" do
|
96
|
+
@vader.is?(@vader).should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not be @vader" do
|
100
|
+
@vader.is?(@leia).should_not be_true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should return vader and luke friends in common" do
|
104
|
+
@vader.friends_in_common_with(@luke).to_set.should == [@leia].to_set
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should return vader and luke friends not in common" do
|
108
|
+
create_friendship @vader, @han_solo
|
109
|
+
@vader.friends_not_in_common_with(@luke).to_set.should ==
|
110
|
+
[@han_solo].to_set
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should return friends of vader's friends" do
|
114
|
+
@vader.friends_of_friends.to_set.should == [@yoda, @han_solo].to_set
|
115
|
+
end
|
116
|
+
|
117
|
+
it "vader and yoda should not be friends" do
|
118
|
+
@vader.friends?(@yoda).should be_false
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should destroy friendship" do
|
122
|
+
expect {
|
123
|
+
@vader.destroy_friendship_with(@luke)
|
124
|
+
}.to change(Friendship, :count).by(-2)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "friendship request" do
|
129
|
+
it "requested_at should not be nil" do
|
130
|
+
friendship, status = @vader.be_friends_with(@luke)
|
131
|
+
|
132
|
+
friendship.requested_at.should_not be_nil
|
133
|
+
end
|
134
|
+
|
135
|
+
it "accepted_at should be nil" do
|
136
|
+
friendship, status = @vader.be_friends_with(@luke)
|
137
|
+
|
138
|
+
friendship.accepted_at.should be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should return nil and 'friend is required' status" do
|
142
|
+
friendship, status = @vader.be_friends_with(nil)
|
143
|
+
|
144
|
+
friendship.should be_nil
|
145
|
+
status.should == Friendship::STATUS_FRIEND_IS_REQUIRED
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should return nil and 'is you' status" do
|
149
|
+
friendship, status = @vader.be_friends_with(@vader)
|
150
|
+
|
151
|
+
friendship.should be_nil
|
152
|
+
status.should == Friendship::STATUS_IS_YOU
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should return nil and 'already friends status" do
|
156
|
+
@vader.be_friends_with(@luke)
|
157
|
+
@luke.be_friends_with(@vader)
|
158
|
+
friendship, status = @vader.be_friends_with(@luke)
|
159
|
+
|
160
|
+
friendship.should be_nil
|
161
|
+
status.should == Friendship::STATUS_ALREADY_FRIENDS
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return nil and 'already requested' status" do
|
165
|
+
@vader.be_friends_with(@luke)
|
166
|
+
friendship, status = @vader.be_friends_with(@luke)
|
167
|
+
|
168
|
+
friendship.should be_nil
|
169
|
+
status.should == Friendship::STATUS_ALREADY_REQUESTED
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should return friendship and 'accepted friendship' status" do
|
173
|
+
@vader.be_friends_with(@luke)
|
174
|
+
friendship, status = @luke.be_friends_with(@vader)
|
175
|
+
|
176
|
+
friendship.should be_kind_of(Friendship)
|
177
|
+
status.should == Friendship::STATUS_FRIENDSHIP_ACCEPTED
|
178
|
+
@vader.should be_friends(@luke)
|
179
|
+
@luke.should be_friends(@vader)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should update accepted_at when accept friendship request" do
|
183
|
+
@vader.be_friends_with(@luke)
|
184
|
+
friendship, status = @luke.be_friends_with(@vader)
|
185
|
+
|
186
|
+
friendship.accepted_at.should_not be_nil
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should create friendships" do
|
190
|
+
doing {
|
191
|
+
@vader.be_friends_with(@luke)
|
192
|
+
|
193
|
+
@vader.friendships.count.should == 1
|
194
|
+
@luke.friendships.count.should == 1
|
195
|
+
}.should change(Friendship, :count).by(2)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe Friendship do
|
200
|
+
it "should be pending status" do
|
201
|
+
@friendship = Friendship.new(:status => 'pending')
|
202
|
+
@friendship.should be_pending
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should be accepted status" do
|
206
|
+
@friendship = Friendship.new(:status => 'accepted')
|
207
|
+
@friendship.should be_accepted
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should be requested status" do
|
211
|
+
@friendship = Friendship.new(:status => 'requested')
|
212
|
+
@friendship.should be_requested
|
213
|
+
end
|
214
|
+
|
215
|
+
context "when attaching has_many" do
|
216
|
+
before do
|
217
|
+
class Thing < ActiveRecord::Base
|
218
|
+
belongs_to :friendship
|
219
|
+
end
|
220
|
+
|
221
|
+
class Friendship < ActiveRecord::Base
|
222
|
+
has_many :things, :dependent => :destroy
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should destroy related" do
|
227
|
+
@friendships = create_friendship @vader, @han_solo
|
228
|
+
@thing = Thing.create(:friendship => @friendships.first)
|
229
|
+
expect {
|
230
|
+
@vader.destroy
|
231
|
+
}.to change(Thing, :count).by(-1)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "pagination" do
|
237
|
+
before(:each) do
|
238
|
+
pending unless Object.const_defined?('Paginate')
|
239
|
+
|
240
|
+
create_friendship @vader, @luke
|
241
|
+
create_friendship @vader, @leia
|
242
|
+
create_friendship @vader, @han_solo
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should paginate friends" do
|
246
|
+
@vader.friends.paginate(:limit => 1).to_a.should == [@luke, @leia]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
def create_friendship(user1, user2)
|
253
|
+
user1.be_friends_with(user2)
|
254
|
+
user2.be_friends_with(user1)
|
255
|
+
end
|
256
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
begin
|
3
|
+
drop_table :users
|
4
|
+
drop_table :friendships
|
5
|
+
rescue
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :users do |t|
|
9
|
+
t.string :login
|
10
|
+
t.integer :friends_count, :default => 0, :null => false
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :friendships do |t|
|
14
|
+
t.references :user, :friend
|
15
|
+
t.string :status
|
16
|
+
t.datetime :requested_at, :null => false
|
17
|
+
t.datetime :accepted_at, :null => true, :default => nil
|
18
|
+
end
|
19
|
+
|
20
|
+
create_table :things do |t|
|
21
|
+
t.references :friendship
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "active_record"
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ":memory:"}}
|
6
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"])
|
7
|
+
|
8
|
+
load("schema.rb")
|
9
|
+
require 'has_friends'
|
10
|
+
|
11
|
+
class Object
|
12
|
+
def self.unset_class(*args)
|
13
|
+
class_eval do
|
14
|
+
args.each do |klass|
|
15
|
+
eval(klass) rescue nil
|
16
|
+
remove_const(klass) if const_defined?(klass)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias :doing :lambda
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redu-has_friends
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- jessicabarbalho, guiocavalcanti
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: activerecord
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.2'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.2'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sqlite3
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: shoulda-matchers
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: debugger
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: Permite que o usuário se relacione com outros usuários dentro de uma
|
127
|
+
aplicação rails por meio de amizades
|
128
|
+
email:
|
129
|
+
- jessica@redu.com.br
|
130
|
+
- guilhermec@redu.com.br
|
131
|
+
executables: []
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- .gitignore
|
136
|
+
- .travis.yml
|
137
|
+
- CHANGELOG.mkd
|
138
|
+
- Gemfile
|
139
|
+
- MIT-LICENSE
|
140
|
+
- README.markdown
|
141
|
+
- Rakefile
|
142
|
+
- has_friends.gemspec
|
143
|
+
- lib/friendship.rb
|
144
|
+
- lib/has_friends.rb
|
145
|
+
- lib/version.rb
|
146
|
+
- spec/has_friends_spec.rb
|
147
|
+
- spec/schema.rb
|
148
|
+
- spec/spec_helper.rb
|
149
|
+
homepage: https://github.com/redu/has_friends
|
150
|
+
licenses: []
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
segments:
|
162
|
+
- 0
|
163
|
+
hash: -2774400783712300662
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
166
|
+
requirements:
|
167
|
+
- - ! '>='
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
segments:
|
171
|
+
- 0
|
172
|
+
hash: -2774400783712300662
|
173
|
+
requirements: []
|
174
|
+
rubyforge_project: has_friends
|
175
|
+
rubygems_version: 1.8.25
|
176
|
+
signing_key:
|
177
|
+
specification_version: 3
|
178
|
+
summary: Adiciona suporte a amizado numa aplicação rails
|
179
|
+
test_files:
|
180
|
+
- spec/has_friends_spec.rb
|
181
|
+
- spec/schema.rb
|
182
|
+
- spec/spec_helper.rb
|