kabari-dm-is-friendly 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
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, :child_key => [:gangster_id]
54
+ belongs_to :homie, :class_name => "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 = "manbehindtheman@kabari.name"
13
+ gem.homepage = "http://github.com/kabari/dm-is-friendly"
14
+ gem.authors = ["Kabari Hendrick"]
15
+ gem.add_dependency("extlib", "~> #{version}")
16
+ gem.add_dependency("dm-core", "~> #{version}")
17
+ gem.add_dependency("dm-aggregates", "~> #{version}")
18
+ end
19
+
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.9.11
@@ -0,0 +1,58 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{dm-is-friendly}
5
+ s.version = "0.9.11"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Kabari Hendrick"]
9
+ s.date = %q{2009-06-15}
10
+ s.email = %q{manbehindtheman@kabari.name}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.markdown"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.markdown",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "dm-is-friendly.gemspec",
23
+ "lib/dm-is-friendly.rb",
24
+ "lib/is/friendly.rb",
25
+ "lib/is/version.rb",
26
+ "spec/dm-is-friendly_spec.rb",
27
+ "spec/spec.opts",
28
+ "spec/spec_helper.rb"
29
+ ]
30
+ s.homepage = %q{http://github.com/kabari/dm-is-friendly}
31
+ s.rdoc_options = ["--charset=UTF-8"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.3.3}
34
+ s.summary = %q{DataMapper plugin that adds self-referential friendship functionality to your models.}
35
+ s.test_files = [
36
+ "spec/dm-is-friendly_spec.rb",
37
+ "spec/spec_helper.rb"
38
+ ]
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ s.add_runtime_dependency(%q<extlib>, ["~> 0.9.11"])
46
+ s.add_runtime_dependency(%q<dm-core>, ["~> 0.9.11"])
47
+ s.add_runtime_dependency(%q<dm-aggregates>, ["~> 0.9.11"])
48
+ else
49
+ s.add_dependency(%q<extlib>, ["~> 0.9.11"])
50
+ s.add_dependency(%q<dm-core>, ["~> 0.9.11"])
51
+ s.add_dependency(%q<dm-aggregates>, ["~> 0.9.11"])
52
+ end
53
+ else
54
+ s.add_dependency(%q<extlib>, ["~> 0.9.11"])
55
+ s.add_dependency(%q<dm-core>, ["~> 0.9.11"])
56
+ s.add_dependency(%q<dm-aggregates>, ["~> 0.9.11"])
57
+ end
58
+ end
@@ -0,0 +1,26 @@
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.11'
7
+ require "extlib"
8
+
9
+ gem 'dm-core', '~>0.9.11'
10
+ require 'dm-core'
11
+
12
+ gem 'dm-aggregates', '~>0.9.11'
13
+ require "dm-aggregates"
14
+
15
+ # Require plugin-files
16
+ require Pathname(__FILE__).dirname.expand_path / 'is' / 'friendly'
17
+
18
+ # Include the plugin in Resource
19
+ # module DataMapper
20
+ # module Model
21
+ # include DataMapper::Is::Friendly
22
+ # end # module Model
23
+ # end # module DataMapper
24
+
25
+ # An alternative way to do the same thing as above:
26
+ DataMapper::Model.append_extensions(DataMapper::Is::Friendly)
@@ -0,0 +1,159 @@
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_config = FriendlyConfig.new(self, options)
9
+ class << self; self; end.class_eval do
10
+ attr_reader :friendly_config
11
+ def friendly_config; @friendly_config; end
12
+ end
13
+
14
+ class_eval(<<-EOS,(__FILE__),(__LINE__)
15
+ has n, :friendships, :class_name => "#{friendly_config.friendship_class.name}"
16
+ has n, :friends_by_me, :through => :friendships, :class_name => "#{self.name}",
17
+ :child_key => [:#{Extlib::Inflection.foreign_key(self.name)}]
18
+ has n, :friended_by, :through => :friendships, :class_name => "#{self.name}",
19
+ :remote_name => "#{self.name.downcase}", :child_key => [:friend_id]
20
+ EOS
21
+ )
22
+
23
+ # stuff like this didn't work as of DM 0.9.10, hence the mass amounts of hand ql queries
24
+ # returns all the people I have requested frienship from
25
+ # has n, :friendship_requests, :through => :friendships, :class_name => "Person",
26
+ # :child_key => [:person_id]
27
+ # returns all the people that have requested my friendship
28
+ # has n, :friendships_to_accept, :through => :friendships, :class_name => "Person",
29
+ # :remote_name => :person, :child_key => [:friend_id]
30
+
31
+ include DataMapper::Is::Friendly::InstanceMethods
32
+ end
33
+
34
+ class FriendlyConfig
35
+ attr_reader :friendship_class, :friend_class
36
+
37
+ def initialize(klazz, opts)
38
+ @friendship_class = Object.full_const_get(opts[:friendship_class])
39
+ @friend_class = klazz
40
+ @require_acceptance = opts[:require_acceptance]
41
+ end
42
+
43
+ def friendship_foreign_key
44
+ Extlib::Inflection.foreign_key(friend_class.name)
45
+ end
46
+
47
+ def friend_foreign_key
48
+ Extlib::Inflection.foreign_key(friendship_class.name)
49
+ end
50
+
51
+ def friend_table_name
52
+ Extlib::Inflection.tableize(friend_class.name)
53
+ end
54
+
55
+ def friendship_table_name
56
+ Extlib::Inflection.tableize(friendship_class.name)
57
+ end
58
+
59
+ def require_acceptance?
60
+ @require_acceptance
61
+ end
62
+ end
63
+
64
+ module InstanceMethods
65
+
66
+ def friends
67
+ friends_sql = <<-SQL
68
+ SELECT #{friendly_config.friend_table_name}.* FROM #{friendly_config.friend_table_name} INNER JOIN #{friendly_config.friendship_table_name}
69
+ ON #{friendly_config.friend_table_name}.id = #{friendly_config.friendship_table_name}.#{friendly_config.friendship_foreign_key} WHERE ((#{friendly_config.friendship_table_name}.friend_id = #{id}) #{acceptance_sql(true)})
70
+ UNION
71
+ SELECT #{friendly_config.friend_table_name}.* FROM #{friendly_config.friend_table_name} INNER JOIN #{friendly_config.friendship_table_name}
72
+ ON #{friendly_config.friend_table_name}.id = #{friendly_config.friendship_table_name}.friend_id WHERE ((#{friendly_config.friendship_table_name}.#{friendly_config.friendship_foreign_key} = #{id}) #{acceptance_sql(true)})
73
+ SQL
74
+
75
+ self.class.find_by_sql(friends_sql)
76
+ end
77
+
78
+ # returns all the people I have requested frienship from
79
+ def friendship_requests(friend = nil)
80
+ sql = [%{SELECT #{friendly_config.friend_table_name}.* FROM #{friendly_config.friend_table_name} INNER JOIN #{friendly_config.friendship_table_name}}]
81
+ sql << %{ON #{friendly_config.friend_table_name}.id = #{friendly_config.friendship_table_name}.friend_id}
82
+ sql << %{WHERE ((#{friendly_config.friendship_table_name}.#{friendly_config.friendship_foreign_key} = #{id}) #{acceptance_sql}}
83
+ sql << select_friendship_sql(friend) if friend
84
+ sql << ") #{'LIMIT 1' if friend}"
85
+ self.class.find_by_sql(sql.join(' '))
86
+ end
87
+
88
+ # returns all the people that have requested my friendship
89
+ def friendships_to_accept(friend = nil)
90
+ sql = [%{SELECT #{friendly_config.friend_table_name}.* FROM #{friendly_config.friend_table_name} INNER JOIN #{friendly_config.friendship_table_name}}]
91
+ sql << %{ON #{friendly_config.friend_table_name}.id = #{friendly_config.friendship_table_name}.#{friendly_config.friendship_foreign_key}}
92
+ sql << %{WHERE ((#{friendly_config.friendship_table_name}.friend_id = #{id}) #{acceptance_sql}}
93
+ sql << select_friendship_sql(friend,true) if friend
94
+ sql << ") #{'LIMIT 1' if friend}"
95
+ self.class.find_by_sql(sql.join(' '))
96
+ end
97
+
98
+ # see if there is a pending friendship request from this person to another
99
+ def friendship_requested?(friend)
100
+ # return false unless friendly_config.require_acceptance?
101
+ !friendship_requests(friend).empty? #.detect{|f| f.friend_id = friend.id} #.first('friendships.friend_id' => friend.id)
102
+ end
103
+
104
+ # see if user has a friend request to accept from this person
105
+ def friendship_to_accept?(friend)
106
+ return false unless friendly_config.require_acceptance?
107
+ !friendships_to_accept(friend).empty? #first('friendships.person_id' => friend.id)
108
+ end
109
+
110
+ # Accepts a user object and returns true if both users are
111
+ # friends and the friendship has been accepted.
112
+ def is_friends_with?(friend)
113
+ !self.friendship(friend).nil?
114
+ end
115
+
116
+ # request friendship from "friend"
117
+ def request_friendship(friend)
118
+ return false if friendship(friend)
119
+ self.friendships.create(:friend => friend)
120
+ end
121
+
122
+ # Accepts a user object and updates an existing friendship to
123
+ # be accepted.
124
+ def confirm_friendship_with(friend)
125
+ self.friendship(friend,{:accepted_at => nil}).update_attributes({:accepted_at => Time.now})
126
+ # reload so old relationship won't be lingering
127
+ friend.reload
128
+ self.reload
129
+ end
130
+
131
+ # Accepts a user object and deletes a friendship between both
132
+ # users.
133
+ def end_friendship_with(friend)
134
+ self.friendship(friend).destroy if self.is_friends_with?(friend)
135
+ end
136
+
137
+ protected
138
+ # Accepts a user object and returns the friendship object
139
+ # associated with both users.
140
+ def friendship(friend, opts = {})
141
+ friendly_config.friendship_class.first({:conditions => ["(#{friendly_config.friendship_foreign_key} = ? AND friend_id = ?) OR (friend_id = ? AND #{friendly_config.friendship_foreign_key} = ?)", self.id, friend.id, self.id, friend.id]}.merge(opts) )
142
+ end
143
+
144
+ def friendly_config; self.class.friendly_config; end
145
+
146
+ private
147
+ def acceptance_sql(accepted = false)
148
+ "AND #{friendly_config.friendship_table_name}.accepted_at IS #{accepted ? 'NOT' : ''} NULL" if friendly_config.require_acceptance?
149
+ end
150
+
151
+ # because of DM bug in 0.9.10
152
+ def select_friendship_sql(friend, for_me = false)
153
+ "AND #{friendly_config.friendship_table_name}.#{for_me ? friendly_config.friendship_foreign_key : 'friend_id'} = #{friend.id}"
154
+ end
155
+
156
+ end
157
+ end # Friendly
158
+ end # Is
159
+ end # DataMapper
data/lib/is/version.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "yaml"
2
+
3
+ module DataMapper
4
+ module Is
5
+ module Friendly
6
+ VERSION = File.open(File.join(File.dirname(__FILE__), *%w[.. .. VERSION])) { |file| YAML.load(file) }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,187 @@
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, :nullable => true
8
+
9
+ belongs_to :person, :child_key => [:person_id]
10
+ belongs_to :friend, :class_name => "Person", :child_key => [:friend_id]
11
+
12
+ end
13
+
14
+ class Person
15
+ include DataMapper::Resource
16
+ property :id, Integer, :serial => true
17
+ property :name, String
18
+ is :friendly
19
+ end
20
+
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 config" do
28
+ Person.friendly_config.friendship_class.should == Friendship
29
+ Person.friendly_config.friend_class.should == Person
30
+ Person.friendly_config.friendship_foreign_key.should == "person_id"
31
+ Person.friendly_config.friend_table_name.should == "people"
32
+ Person.friendly_config.friendship_table_name.should == "friendships"
33
+ Person.friendly_config.require_acceptance?.should == true
34
+ end
35
+ end
36
+
37
+ describe 'DataMapper::Is::Friendly', "with friendships" do
38
+ before(:all) do
39
+ Friendship.auto_migrate!; Person.auto_migrate!
40
+
41
+ @quentin = Person.create(:name => "quentin")
42
+ @aaron = Person.create(:name => "aaron") # state: "pending"
43
+ @joe = Person.create(:name => "joe")
44
+ end
45
+
46
+ it "should work" do
47
+ lambda do
48
+ @joe.request_friendship(@quentin)
49
+ end.should change(Friendship, :count).by(1)
50
+ end
51
+
52
+ it "should only recognize friends that are confirmed" do
53
+ @joe.friends.should_not include(@quentin)
54
+ @quentin.friends.should_not include(@joe)
55
+ end
56
+
57
+ it "should set the proper relationships" do
58
+ # see if associations are correct
59
+ @quentin.friendship_requests.should_not include(@joe)
60
+ @joe.friendship_requests.should include(@quentin)
61
+ @quentin.friendships_to_accept.should include(@joe)
62
+ @joe.friendships_to_accept.should_not include(@quentin)
63
+ end
64
+
65
+ it "should also work with convenience methods" do
66
+ @quentin.friendship_to_accept?(@joe).should be_true
67
+ @joe.friendship_requested?(@quentin).should be_true
68
+ end
69
+
70
+ it "should have to be confirmed" do
71
+ # confirm the request
72
+ @quentin.confirm_friendship_with(@joe)
73
+
74
+ # see if associations are correct
75
+ @quentin.friends.should include(@joe)
76
+ @joe.friends.should include(@quentin)
77
+
78
+ @quentin.friendship_to_accept?(@joe).should be_false
79
+ @joe.friendship_requested?(@quentin).should be_false
80
+ end
81
+
82
+ it "should not be added twice" do
83
+ lambda do
84
+ @joe.request_friendship(@quentin)
85
+ @joe.should have(1).friends
86
+ @quentin.should have(1).friends
87
+ end.should_not change(Friendship,:count)
88
+ end
89
+
90
+ it "should be able to have multiple friends" do
91
+ @joe.request_friendship(@aaron)
92
+ @joe.friendship_requested?(@aaron).should be_true
93
+ @aaron.friendship_to_accept?(@joe).should be_true
94
+ end
95
+
96
+ it "should be able to delete friendships" do
97
+ lambda do
98
+ # joe sleeps with quentin's wife perhaps
99
+ @quentin.end_friendship_with(@joe)
100
+ end.should change(Friendship,:count)
101
+
102
+ @quentin.reload; @joe.reload
103
+
104
+ @quentin.friends.should_not include(@joe)
105
+ @joe.friends.should_not include(@quentin)
106
+ end
107
+
108
+ end
109
+
110
+ # new classes
111
+ class Homie
112
+ include DataMapper::Resource
113
+ property :gangster_id, Integer, :key => true
114
+ property :friend_id, Integer, :key => true
115
+
116
+ belongs_to :gangster, :child_key => [:gangster_id]
117
+ belongs_to :friend, :class_name => "Gangster", :child_key => [:friend_id]
118
+
119
+ end
120
+
121
+ class Gangster
122
+ include DataMapper::Resource
123
+ property :id, Integer, :serial => true
124
+ property :name, String
125
+ is :friendly, :friendship_class => "Homie", :require_acceptance => false
126
+ end
127
+
128
+ describe 'DataMapper::Is::Friendly', "with changed options" do
129
+ before(:all) do
130
+ Homie.auto_migrate!; Gangster.auto_migrate!
131
+
132
+ @quentin = Gangster.create(:name => "quentin")
133
+ @aaron = Gangster.create(:name => "aaron") # state: "pending"
134
+ @joe = Gangster.create(:name => "joe")
135
+ end
136
+
137
+ it "should work" do
138
+ lambda do
139
+ @joe.request_friendship(@quentin)
140
+ end.should change(Homie, :count).by(1)
141
+ end
142
+
143
+ it "should recognize every friend request" do
144
+ @joe.friends.should include(@quentin)
145
+ @quentin.friends.should include(@joe)
146
+ end
147
+
148
+ it "should set the proper relationships" do
149
+ # see if associations are correct
150
+ @quentin.friendship_requests.should_not include(@joe)
151
+ @joe.friendship_requests.should include(@quentin)
152
+ @quentin.friendships_to_accept.should include(@joe)
153
+ @joe.friendships_to_accept.should_not include(@quentin)
154
+ end
155
+
156
+ it "should not need acceptance" do
157
+ @quentin.friendship_to_accept?(@joe).should be_false
158
+ @joe.friendship_requested?(@quentin).should be_true
159
+ end
160
+
161
+ it "should not be added twice" do
162
+ lambda do
163
+ @joe.request_friendship(@quentin)
164
+ @joe.should have(1).friends
165
+ @quentin.should have(1).friends
166
+ end.should_not change(Homie,:count)
167
+ end
168
+
169
+ it "should be able to have multiple friends" do
170
+ @joe.request_friendship(@aaron)
171
+ @joe.friendship_requested?(@aaron).should be_true
172
+ @aaron.friendship_to_accept?(@joe).should be_false
173
+ end
174
+
175
+ it "should be able to delete friendships" do
176
+ lambda do
177
+ # joe sleeps with quentin's wife perhaps
178
+ @quentin.end_friendship_with(@joe)
179
+ end.should change(Homie,:count)
180
+
181
+ @quentin.reload; @joe.reload
182
+
183
+ @quentin.friends.should_not include(@joe)
184
+ @joe.friends.should_not include(@quentin)
185
+ end
186
+
187
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
@@ -0,0 +1,26 @@
1
+ require 'pathname'
2
+ require 'rubygems'
3
+
4
+ gem 'rspec', '~>1.2.6'
5
+ require 'spec'
6
+
7
+ require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-friendly'
8
+
9
+ def load_driver(name, default_uri)
10
+ return false if ENV['ADAPTER'] != name.to_s
11
+
12
+ begin
13
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
14
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
15
+ true
16
+ rescue LoadError => e
17
+ warn "Could not load do_#{name}: #{e}"
18
+ false
19
+ end
20
+ end
21
+
22
+ ENV['ADAPTER'] ||= 'sqlite3'
23
+
24
+ HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
25
+ HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
26
+ HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kabari-dm-is-friendly
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.11
5
+ platform: ruby
6
+ authors:
7
+ - Kabari Hendrick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-15 00:00:00 -07: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.11
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.9.11
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.9.11
44
+ version:
45
+ description:
46
+ email: manbehindtheman@kabari.name
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: false
69
+ homepage: http://github.com/kabari/dm-is-friendly
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --charset=UTF-8
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.2.0
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: DataMapper plugin that adds self-referential friendship functionality to your models.
94
+ test_files:
95
+ - spec/dm-is-friendly_spec.rb
96
+ - spec/spec_helper.rb