dm-is-friendly 0.10.2
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/.document +5 -0
- data/.gitignore +6 -0
- data/LICENSE +20 -0
- data/README.markdown +63 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/dm-is-friendly.gemspec +62 -0
- data/lib/dm-is-friendly.rb +19 -0
- data/lib/is/friendly.rb +131 -0
- data/lib/is/version.rb +10 -0
- data/spec/dm-is-friendly_spec.rb +189 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +35 -0
- metadata +98 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Kabari Hendrick
|
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,63 @@
|
|
1
|
+
# dm-is-friendly #
|
2
|
+
|
3
|
+
DataMapper plugin that adds self-referential friendship functionality to your models.
|
4
|
+
|
5
|
+
**Note: This is NOT officially part of the DataMapper (dm-core, dm-more) project, it just works with DataMapper.
|
6
|
+
|
7
|
+
## Why is this plugin useful? ##
|
8
|
+
|
9
|
+
If you're building a social app, it will probably save you 12 minutes, tops.
|
10
|
+
|
11
|
+
## Installation ##
|
12
|
+
|
13
|
+
Probably make sure you can use github gems first.
|
14
|
+
|
15
|
+
$ sudo gem install kabari-dm-is-friendly.
|
16
|
+
|
17
|
+
Create a file for the friendship (or whatever you want to call it) class. An example is below.
|
18
|
+
|
19
|
+
## Example DataMapper resource (i.e. model) ##
|
20
|
+
|
21
|
+
# /app/models/friendship.rb
|
22
|
+
class Friendship
|
23
|
+
include DataMapper::Resource
|
24
|
+
|
25
|
+
# you need all of this
|
26
|
+
property :person_id, Integer, :key => true
|
27
|
+
property :friend_id, Integer, :key => true
|
28
|
+
property :accepted_at, DateTime, :nullable => true
|
29
|
+
|
30
|
+
belongs_to :person, :child_key => [:person_id]
|
31
|
+
belongs_to :friend, :class_name => "Person", :child_key => [:friend_id]
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# /app/models/person.rb
|
36
|
+
class Person
|
37
|
+
include DataMapper::Resource
|
38
|
+
property :id, Integer, :serial => true
|
39
|
+
property :name, String
|
40
|
+
|
41
|
+
# you need this part
|
42
|
+
is :friendly
|
43
|
+
end
|
44
|
+
|
45
|
+
### There are options ###
|
46
|
+
|
47
|
+
# /some/folder/homie.rb
|
48
|
+
class Homie
|
49
|
+
property :gangster_id, Integer, :key => true
|
50
|
+
property :friend_id, Integer, :key => true
|
51
|
+
property :accepted_at, DateTime, :nullable => true
|
52
|
+
|
53
|
+
belongs_to :gangster
|
54
|
+
belongs_to :homie, :child_key => [:friend_id]
|
55
|
+
end
|
56
|
+
|
57
|
+
# /some/folder/gangster.rb
|
58
|
+
class Gangster
|
59
|
+
is :friendly, :friendship_class => "Homie", :require_acceptance => false
|
60
|
+
end
|
61
|
+
|
62
|
+
This would change the friendship class to Homie, and make it not require friendships to be accepted. I admit, it was kind of dumb to do it that way, but I just made this into a gem so that it wasn't lying around my code base. I'll make it more useful in the next run.
|
63
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require File.join(File.dirname(__FILE__), *%w[lib is version])
|
4
|
+
|
5
|
+
version = DataMapper::Is::Friendly::VERSION
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "dm-is-friendly"
|
11
|
+
gem.summary = %Q{DataMapper plugin that adds self-referential friendship functionality to your models.}
|
12
|
+
gem.email = "kabari@gmail.com"
|
13
|
+
gem.homepage = "http://github.com/kabari/dm-is-friendly"
|
14
|
+
gem.authors = ["Kabari Hendrick"]
|
15
|
+
gem.add_dependency("extlib", "~> 0.9.14")
|
16
|
+
gem.add_dependency("dm-core", "~> #{version}")
|
17
|
+
gem.add_dependency("dm-aggregates", "~> #{version}")
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task :default => :spec
|
38
|
+
|
39
|
+
require 'rake/rdoctask'
|
40
|
+
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "dm-is-friendly #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
47
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.10.2
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{dm-is-friendly}
|
8
|
+
s.version = "0.10.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kabari Hendrick"]
|
12
|
+
s.date = %q{2010-01-11}
|
13
|
+
s.email = %q{kabari@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.markdown",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"dm-is-friendly.gemspec",
|
26
|
+
"lib/dm-is-friendly.rb",
|
27
|
+
"lib/is/friendly.rb",
|
28
|
+
"lib/is/version.rb",
|
29
|
+
"spec/dm-is-friendly_spec.rb",
|
30
|
+
"spec/spec.opts",
|
31
|
+
"spec/spec_helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/kabari/dm-is-friendly}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.5}
|
37
|
+
s.summary = %q{DataMapper plugin that adds self-referential friendship functionality to your models.}
|
38
|
+
s.test_files = [
|
39
|
+
"spec/dm-is-friendly_spec.rb",
|
40
|
+
"spec/spec_helper.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_runtime_dependency(%q<extlib>, ["~> 0.9.14"])
|
49
|
+
s.add_runtime_dependency(%q<dm-core>, ["~> 0.10.2"])
|
50
|
+
s.add_runtime_dependency(%q<dm-aggregates>, ["~> 0.10.2"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<extlib>, ["~> 0.9.14"])
|
53
|
+
s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
|
54
|
+
s.add_dependency(%q<dm-aggregates>, ["~> 0.10.2"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<extlib>, ["~> 0.9.14"])
|
58
|
+
s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
|
59
|
+
s.add_dependency(%q<dm-aggregates>, ["~> 0.10.2"])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Needed to import datamapper and other gems
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
# Add all external dependencies for the plugin here
|
6
|
+
gem 'extlib', '~>0.9.14'
|
7
|
+
require "extlib"
|
8
|
+
|
9
|
+
gem 'dm-core', '~>0.10.2'
|
10
|
+
require 'dm-core'
|
11
|
+
|
12
|
+
gem 'dm-aggregates', '~>0.10.2'
|
13
|
+
require "dm-aggregates"
|
14
|
+
|
15
|
+
# Require plugin-files
|
16
|
+
require Pathname(__FILE__).dirname.expand_path / 'is' / 'friendly'
|
17
|
+
|
18
|
+
# Include the plugin in Model
|
19
|
+
DataMapper::Model.append_extensions(DataMapper::Is::Friendly)
|
data/lib/is/friendly.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# Home baked self-referential :through relationship
|
2
|
+
module DataMapper
|
3
|
+
module Is
|
4
|
+
module Friendly
|
5
|
+
|
6
|
+
def is_friendly(options = {})
|
7
|
+
options = {:require_acceptance => true, :friendship_class => "Friendship" }.merge(options)
|
8
|
+
@friendly_options = FriendlyConfig.new(self, options)
|
9
|
+
def self.friendly_options; @friendly_options; end
|
10
|
+
|
11
|
+
class_eval(<<-RUBY,(__FILE__),(__LINE__+1)
|
12
|
+
has n, :friendships, :model => #{options[:friendship_class]}
|
13
|
+
has n, :friends_by_me, :through => :friendships, :model => "#{self.name}", :via => :#{self.name.downcase}
|
14
|
+
has n, :friended_by, :through => :friendships, :model => "#{self.name}",
|
15
|
+
:via => :#{self.name.downcase}
|
16
|
+
RUBY
|
17
|
+
)
|
18
|
+
|
19
|
+
include DataMapper::Is::Friendly::InstanceMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
# This class holds the configuration options for the plugin.
|
23
|
+
class FriendlyConfig
|
24
|
+
attr_reader :friend_class, :friendship_foreign_key, :friend_foreign_key
|
25
|
+
|
26
|
+
def initialize(klazz, opts)
|
27
|
+
@friend_class = klazz
|
28
|
+
@friendship_class_name = opts[:friendship_class]
|
29
|
+
@friendship_foreign_key = Extlib::Inflection.foreign_key(@friend_class.name).to_sym
|
30
|
+
@friend_foreign_key = Extlib::Inflection.foreign_key(@friendship_class_name).to_sym
|
31
|
+
@require_acceptance = opts[:require_acceptance]
|
32
|
+
end
|
33
|
+
|
34
|
+
def friendship_class
|
35
|
+
Object.full_const_get(@friendship_class_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_acceptance?
|
39
|
+
@require_acceptance
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module InstanceMethods
|
44
|
+
|
45
|
+
# returns all of the friends this person has that are accepted
|
46
|
+
def friends
|
47
|
+
friendship_requests(nil,true).union(friendships_to_accept(nil,true))
|
48
|
+
end
|
49
|
+
|
50
|
+
# returns all the people I have requested frienship from
|
51
|
+
def friendship_requests(friend = nil, include_accepted = false)
|
52
|
+
conditions = {}
|
53
|
+
friend_acceptance_condition(conditions, include_accepted)
|
54
|
+
friend_scope_condition(conditions, friend)
|
55
|
+
|
56
|
+
conditions[friendly_options.friendship_foreign_key] = self.id
|
57
|
+
ids = friendly_options.friendship_class.all(conditions).collect(&:friend_id)
|
58
|
+
self.class.all( :id => ids)
|
59
|
+
end
|
60
|
+
|
61
|
+
# returns all the people that have requested my friendship
|
62
|
+
def friendships_to_accept(friend = nil, include_accepted = false)
|
63
|
+
conditions = {}
|
64
|
+
friend_acceptance_condition(conditions, include_accepted)
|
65
|
+
friend_scope_condition(conditions, friend, true)
|
66
|
+
|
67
|
+
conditions[:friend_id] = self.id
|
68
|
+
ids = friendly_options.friendship_class.all(conditions).collect(&friendly_options.friendship_foreign_key)
|
69
|
+
self.class.all(:id => ids)
|
70
|
+
end
|
71
|
+
|
72
|
+
# see if there is a pending friendship request from this person to another
|
73
|
+
def friendship_requested?(friend)
|
74
|
+
# return false unless friendly_options.require_acceptance?
|
75
|
+
!friendship_requests(friend).empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
# see if user has a friend request to accept from this person
|
79
|
+
def friendship_to_accept?(friend)
|
80
|
+
return false unless friendly_options.require_acceptance?
|
81
|
+
!friendships_to_accept(friend).empty?
|
82
|
+
end
|
83
|
+
|
84
|
+
# Accepts a user object and returns true if both users are
|
85
|
+
# friends and the friendship has been accepted.
|
86
|
+
def is_friends_with?(friend)
|
87
|
+
!self.friendship(friend).nil?
|
88
|
+
end
|
89
|
+
|
90
|
+
# request friendship from "friend"
|
91
|
+
def request_friendship(friend)
|
92
|
+
return false if friendship(friend)
|
93
|
+
self.friendships.create(:friend => friend)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Accepts a user and updates an existing friendship to be accepted.
|
97
|
+
def confirm_friendship_with(friend)
|
98
|
+
self.friendship(friend,{:accepted_at => nil}).update({:accepted_at => Time.now})
|
99
|
+
# reload so old relationship won't be lingering in the IdentityMap
|
100
|
+
friend.reload
|
101
|
+
self.reload
|
102
|
+
end
|
103
|
+
|
104
|
+
# Accepts a user and deletes a friendship between both users.
|
105
|
+
def end_friendship_with(friend)
|
106
|
+
self.friendship(friend).destroy if self.is_friends_with?(friend)
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
# Accepts a user and returns the friendship associated with both users.
|
111
|
+
def friendship(friend, opts = {})
|
112
|
+
friendly_options.friendship_class.first({:conditions => ["(#{friendly_options.friendship_foreign_key} = ? AND friend_id = ?) OR (friend_id = ? AND #{friendly_options.friendship_foreign_key} = ?)", self.id, friend.id, self.id, friend.id]}.merge(opts) )
|
113
|
+
end
|
114
|
+
|
115
|
+
def friendly_options; self.class.friendly_options; end
|
116
|
+
|
117
|
+
private
|
118
|
+
def friend_acceptance_condition(conditions, accepted = false)
|
119
|
+
accepted ? (conditions[:accepted_at.not] = nil) : (conditions[:accepted_at] = nil) if friendly_options.require_acceptance?
|
120
|
+
end
|
121
|
+
|
122
|
+
def friend_scope_condition(conditions, friend = nil, for_me = false)
|
123
|
+
return unless friend
|
124
|
+
key_name = for_me ? friendly_options.friendship_foreign_key : :friend_id
|
125
|
+
conditions[key_name] = friend.id
|
126
|
+
conditions[:limit] = 1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end # Friendly
|
130
|
+
end # Is
|
131
|
+
end # DataMapper
|
data/lib/is/version.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
class Friendship
|
4
|
+
include DataMapper::Resource
|
5
|
+
property :person_id, Integer, :key => true
|
6
|
+
property :friend_id, Integer, :key => true
|
7
|
+
property :accepted_at, DateTime, :required => false
|
8
|
+
|
9
|
+
belongs_to :person
|
10
|
+
belongs_to :friend, :model => "Person", :child_key => [:friend_id]
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class Person
|
15
|
+
include DataMapper::Resource
|
16
|
+
property :id, Serial
|
17
|
+
property :name, String
|
18
|
+
|
19
|
+
is :friendly
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'DataMapper::Is::Friendly' do
|
23
|
+
before(:all) do
|
24
|
+
Friendship.auto_migrate!; Person.auto_migrate!
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have proper options set" do
|
28
|
+
Person.friendly_options.friendship_class.should == Friendship
|
29
|
+
Person.friendly_options.friend_class.should == Person
|
30
|
+
Person.friendly_options.friendship_foreign_key.should == :person_id
|
31
|
+
Person.friendly_options.require_acceptance?.should == true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'DataMapper::Is::Friendly', "with friendships" do
|
36
|
+
before(:all) do
|
37
|
+
Friendship.auto_migrate!; Person.auto_migrate!
|
38
|
+
|
39
|
+
@quentin = Person.create(:name => "quentin")
|
40
|
+
@aaron = Person.create(:name => "aaron") # state: "pending"
|
41
|
+
@joe = Person.create(:name => "joe")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should work" do
|
45
|
+
lambda do
|
46
|
+
@joe.request_friendship(@quentin)
|
47
|
+
end.should change(Friendship, :count).by(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should only recognize friends that are confirmed" do
|
51
|
+
@joe.friends.should_not include(@quentin)
|
52
|
+
@quentin.friends.should_not include(@joe)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should set the proper relationships" do
|
56
|
+
# see if associations are correct
|
57
|
+
log("@quention.friendship_requests")
|
58
|
+
@quentin.friendship_requests.should_not include(@joe)
|
59
|
+
log("@joe.friendship_requests")
|
60
|
+
@joe.friendship_requests.should include(@quentin)
|
61
|
+
log("@quention.friendships_to_accept")
|
62
|
+
@quentin.friendships_to_accept.should include(@joe)
|
63
|
+
log("@joe.friendships_to_accept")
|
64
|
+
@joe.friendships_to_accept.should_not include(@quentin)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should also work with convenience methods" do
|
68
|
+
@quentin.friendship_to_accept?(@joe).should be_true
|
69
|
+
@joe.friendship_requested?(@quentin).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should have to be confirmed" do
|
73
|
+
# confirm the request
|
74
|
+
@quentin.confirm_friendship_with(@joe)
|
75
|
+
|
76
|
+
# see if associations are correct
|
77
|
+
@quentin.friends.should include(@joe)
|
78
|
+
@joe.friends.should include(@quentin)
|
79
|
+
|
80
|
+
@quentin.friendship_to_accept?(@joe).should be_false
|
81
|
+
@joe.friendship_requested?(@quentin).should be_false
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should not be added twice" do
|
85
|
+
lambda do
|
86
|
+
@joe.request_friendship(@quentin)
|
87
|
+
@joe.should have(1).friends
|
88
|
+
@quentin.should have(1).friends
|
89
|
+
end.should_not change(Friendship,:count)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be able to have multiple friends" do
|
93
|
+
@joe.request_friendship(@aaron)
|
94
|
+
@joe.friendship_requested?(@aaron).should be_true
|
95
|
+
@aaron.friendship_to_accept?(@joe).should be_true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should be able to delete friendships" do
|
99
|
+
lambda do
|
100
|
+
# joe sleeps with quentin's wife perhaps
|
101
|
+
@quentin.end_friendship_with(@joe)
|
102
|
+
end.should change(Friendship,:count)
|
103
|
+
|
104
|
+
@quentin.reload; @joe.reload
|
105
|
+
|
106
|
+
@quentin.friends.should_not include(@joe)
|
107
|
+
@joe.friends.should_not include(@quentin)
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# new classes
|
113
|
+
class Homie
|
114
|
+
include DataMapper::Resource
|
115
|
+
property :gangster_id, Integer, :key => true
|
116
|
+
property :friend_id, Integer, :key => true
|
117
|
+
|
118
|
+
belongs_to :gangster
|
119
|
+
belongs_to :friend, :model => "Gangster", :child_key => [:friend_id]
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
class Gangster
|
124
|
+
include DataMapper::Resource
|
125
|
+
property :id, Serial
|
126
|
+
property :name, String
|
127
|
+
is :friendly, :friendship_class => "Homie", :require_acceptance => false
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'DataMapper::Is::Friendly', "without requiring acceptance" do
|
131
|
+
before(:all) do
|
132
|
+
Homie.auto_migrate!; Gangster.auto_migrate!
|
133
|
+
|
134
|
+
@quentin = Gangster.create(:name => "quentin")
|
135
|
+
@aaron = Gangster.create(:name => "aaron") # state: "pending"
|
136
|
+
@joe = Gangster.create(:name => "joe")
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should work" do
|
140
|
+
lambda do
|
141
|
+
@joe.request_friendship(@quentin)
|
142
|
+
end.should change(Homie, :count).by(1)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should recognize every friend request" do
|
146
|
+
@joe.friends.should include(@quentin)
|
147
|
+
@quentin.friends.should include(@joe)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should set the proper relationships" do
|
151
|
+
# see if associations are correct
|
152
|
+
@quentin.friendship_requests.should_not include(@joe)
|
153
|
+
@joe.friendship_requests.should include(@quentin)
|
154
|
+
@quentin.friendships_to_accept.should include(@joe)
|
155
|
+
@joe.friendships_to_accept.should_not include(@quentin)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should not need acceptance" do
|
159
|
+
@quentin.friendship_to_accept?(@joe).should be_false
|
160
|
+
@joe.friendship_requested?(@quentin).should be_true
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should not be added twice" do
|
164
|
+
lambda do
|
165
|
+
@joe.request_friendship(@quentin)
|
166
|
+
@joe.should have(1).friends
|
167
|
+
@quentin.should have(1).friends
|
168
|
+
end.should_not change(Homie,:count)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should be able to have multiple friends" do
|
172
|
+
@joe.request_friendship(@aaron)
|
173
|
+
@joe.friendship_requested?(@aaron).should be_true
|
174
|
+
@aaron.friendship_to_accept?(@joe).should be_false
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should be able to delete friendships" do
|
178
|
+
lambda do
|
179
|
+
# joe sleeps with quentin's wife perhaps
|
180
|
+
@quentin.end_friendship_with(@joe)
|
181
|
+
end.should change(Homie,:count)
|
182
|
+
|
183
|
+
@quentin.reload; @joe.reload
|
184
|
+
|
185
|
+
@quentin.friends.should_not include(@joe)
|
186
|
+
@joe.friends.should_not include(@quentin)
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# path to my git clones of the latest dm-core
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), *%w[.. ..]))
|
3
|
+
|
4
|
+
require 'pathname'
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
gem 'rspec', '~>1.2.9'
|
8
|
+
require 'spec'
|
9
|
+
|
10
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-friendly'
|
11
|
+
|
12
|
+
DataMapper::Logger.new("test.log", :debug)
|
13
|
+
|
14
|
+
def load_driver(name, default_uri)
|
15
|
+
return false if ENV['ADAPTER'] != name.to_s
|
16
|
+
|
17
|
+
begin
|
18
|
+
DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
|
19
|
+
DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
|
20
|
+
true
|
21
|
+
rescue LoadError => e
|
22
|
+
warn "Could not load do_#{name}: #{e}"
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
ENV['ADAPTER'] ||= 'sqlite3'
|
28
|
+
|
29
|
+
HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
|
30
|
+
HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_is_friendly_test')
|
31
|
+
HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_is_friendly_test')
|
32
|
+
|
33
|
+
Spec::Runner.configure do |conf|
|
34
|
+
def log(msg); DataMapper.logger.push("****** #{msg}"); end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm-is-friendly
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kabari Hendrick
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-11 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: extlib
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.14
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dm-core
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.10.2
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: dm-aggregates
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.10.2
|
44
|
+
version:
|
45
|
+
description:
|
46
|
+
email: kabari@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
- README.markdown
|
54
|
+
files:
|
55
|
+
- .document
|
56
|
+
- .gitignore
|
57
|
+
- LICENSE
|
58
|
+
- README.markdown
|
59
|
+
- Rakefile
|
60
|
+
- VERSION
|
61
|
+
- dm-is-friendly.gemspec
|
62
|
+
- lib/dm-is-friendly.rb
|
63
|
+
- lib/is/friendly.rb
|
64
|
+
- lib/is/version.rb
|
65
|
+
- spec/dm-is-friendly_spec.rb
|
66
|
+
- spec/spec.opts
|
67
|
+
- spec/spec_helper.rb
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://github.com/kabari/dm-is-friendly
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options:
|
74
|
+
- --charset=UTF-8
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.3.5
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: DataMapper plugin that adds self-referential friendship functionality to your models.
|
96
|
+
test_files:
|
97
|
+
- spec/dm-is-friendly_spec.rb
|
98
|
+
- spec/spec_helper.rb
|