acts_as_amico 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +11 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/API.md +361 -0
  5. data/CHANGELOG.md +16 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +185 -0
  9. data/Rakefile +20 -0
  10. data/acts_as_amico.gemspec +28 -0
  11. data/lib/acts_as_amico/amico_user.rb +69 -0
  12. data/lib/acts_as_amico/railtie.rb +20 -0
  13. data/lib/acts_as_amico/version.rb +3 -0
  14. data/lib/acts_as_amico.rb +9 -0
  15. data/spec/amico/amico_user_spec.rb +700 -0
  16. data/spec/dummy/Rakefile +7 -0
  17. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  18. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  19. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  20. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  21. data/spec/dummy/app/mailers/.gitkeep +0 -0
  22. data/spec/dummy/app/models/.gitkeep +0 -0
  23. data/spec/dummy/app/models/admin.rb +11 -0
  24. data/spec/dummy/app/models/rest_object.rb +7 -0
  25. data/spec/dummy/app/models/thing.rb +3 -0
  26. data/spec/dummy/app/models/user.rb +3 -0
  27. data/spec/dummy/app/models/widget.rb +3 -0
  28. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  29. data/spec/dummy/config/application.rb +44 -0
  30. data/spec/dummy/config/boot.rb +10 -0
  31. data/spec/dummy/config/database.yml +22 -0
  32. data/spec/dummy/config/environment.rb +5 -0
  33. data/spec/dummy/config/environments/development.rb +30 -0
  34. data/spec/dummy/config/environments/production.rb +60 -0
  35. data/spec/dummy/config/environments/test.rb +39 -0
  36. data/spec/dummy/config/initializers/amico.rb +14 -0
  37. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  38. data/spec/dummy/config/initializers/inflections.rb +10 -0
  39. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  40. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  41. data/spec/dummy/config/initializers/session_store.rb +8 -0
  42. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  43. data/spec/dummy/config/locales/en.yml +5 -0
  44. data/spec/dummy/config/routes.rb +58 -0
  45. data/spec/dummy/config.ru +4 -0
  46. data/spec/dummy/db/migrate/20111114184611_create_users.rb +10 -0
  47. data/spec/dummy/db/migrate/20111114184654_create_admins.rb +10 -0
  48. data/spec/dummy/db/migrate/20111114184712_create_things.rb +10 -0
  49. data/spec/dummy/db/migrate/20111114184731_create_widgets.rb +10 -0
  50. data/spec/dummy/db/schema.rb +44 -0
  51. data/spec/dummy/lib/assets/.gitkeep +0 -0
  52. data/spec/dummy/log/.gitkeep +0 -0
  53. data/spec/dummy/public/404.html +26 -0
  54. data/spec/dummy/public/422.html +26 -0
  55. data/spec/dummy/public/500.html +26 -0
  56. data/spec/dummy/public/favicon.ico +0 -0
  57. data/spec/dummy/script/rails +6 -0
  58. data/spec/factories/people.rb +12 -0
  59. data/spec/factories/stuff.rb +11 -0
  60. data/spec/spec_helper.rb +39 -0
  61. metadata +239 -0
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake'
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+
6
+ # encoding: UTF-8
7
+ require 'rubygems'
8
+ begin
9
+ require 'bundler/setup'
10
+ rescue LoadError
11
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
12
+ end
13
+
14
+ RSpec::Core::RakeTask.new(:spec) do |spec|
15
+ spec.pattern = 'spec/**/*_spec.rb'
16
+ spec.rspec_opts = ['--backtrace']
17
+ # spec.ruby_opts = ['-w']
18
+ end
19
+
20
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'acts_as_amico/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "acts_as_amico"
7
+ s.version = ActsAsAmico::VERSION
8
+ s.authors = ["John Metta"]
9
+ s.email = ["mail@johnmetta.com"]
10
+ s.homepage = "https://github.com/mettadore/acts_as_amico"
11
+ s.summary = %q{Rails injectable Relationships (e.g. friendships) backed by Redis}
12
+ s.description = %q{Rails injectable Relationships (e.g. friendships) backed by Redis}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'redis'
20
+ s.add_dependency 'amico'
21
+ s.add_dependency "rails", "~> 3.1.1"
22
+
23
+ s.add_development_dependency "rspec-rails"
24
+ s.add_development_dependency "sqlite3"
25
+ s.add_development_dependency 'factory_girl_rails'
26
+ s.add_development_dependency 'fakeweb'
27
+ s.add_development_dependency 'uuidtools'
28
+ end
@@ -0,0 +1,69 @@
1
+ module ActsAsAmico
2
+ module AmicoUser
3
+
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def amico_key
11
+ @amico_key ||= "id"
12
+ end
13
+ def amico_key= value
14
+ @amico_key = value
15
+ end
16
+
17
+ def acts_as_amico *args
18
+ options = args.extract_options!
19
+ options.assert_valid_keys(:amico_key)
20
+ @amico_key = options[:amico_key] ? options[:amico_key] : "id"
21
+ include ActsAsAmico::AmicoUser::InstanceMethods
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+
27
+ def method_missing(sym, *args, &block)
28
+ if Amico.respond_to? sym
29
+ args[0] = args[0].send(args[0].class.amico_key) if not args[0].nil? and args[0].respond_to?(:id)
30
+ args.unshift(self.send(self.class.amico_key))
31
+ if sym.nil?
32
+ Amico.send(*args, &block)
33
+ else
34
+ Amico.send(sym, *args, &block)
35
+ end
36
+ else
37
+ super
38
+ end
39
+ end
40
+
41
+ def respond_to?(sym)
42
+ pass_sym_to_amico(sym) || super(sym)
43
+ end
44
+
45
+ # Named destructive methods
46
+ def follow! obj, *args
47
+ Amico.follow(self.send(self.class.amico_key), obj.send(obj.class.amico_key), *args)
48
+ end
49
+ def unfollow! obj, *args
50
+ Amico.unfollow(self.send(self.class.amico_key), obj.send(obj.class.amico_key), *args)
51
+ end
52
+ def accept! obj, *args
53
+ Amico.accept(self.send(self.class.amico_key), obj.send(obj.class.amico_key), *args)
54
+ end
55
+ def block! obj, *args
56
+ Amico.block(self.send(self.class.amico_key), obj.send(obj.class.amico_key), *args)
57
+ end
58
+ def unblock! obj, *args
59
+ Amico.unblock(self.send(self.class.amico_key), obj.send(obj.class.amico_key), *args)
60
+ end
61
+
62
+ private
63
+
64
+ def pass_sym_to_amico sym
65
+ Amico.respond_to? sym
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,20 @@
1
+ require 'acts_as_amico'
2
+ require 'rails'
3
+
4
+ module ActsAsAmico
5
+ class Railtie < Rails::Railtie
6
+
7
+ initializer "acts_as_amico.active_record" do |app|
8
+ ActiveSupport.on_load :active_record do
9
+ include ActsAsAmico::AmicoUser
10
+ end
11
+ end
12
+
13
+ initializer "acts_as_amico.active_resource" do |app|
14
+ ActiveSupport.on_load :active_resource do
15
+ include ActsAsAmico::AmicoUser
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module ActsAsAmico
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'redis'
2
+ require 'acts_as_amico'
3
+ require 'acts_as_amico/version'
4
+
5
+ module ActsAsAmico
6
+ autoload :AmicoUser, 'acts_as_amico/amico_user'
7
+
8
+ require 'acts_as_amico/railtie'
9
+ end
@@ -0,0 +1,700 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsAmico do
4
+ describe "acts_as_amico style" do
5
+ before :each do
6
+ @usera = Factory :user
7
+ @userb = Factory :user
8
+ @admin = Factory :admin
9
+ @widget = Factory :widget
10
+ @thing = Factory :thing
11
+ end
12
+
13
+ it "should allow both id and non-id keys" do
14
+ @usera.class.amico_key.should eq("id")
15
+ @admin.class.amico_key.should eq("name")
16
+ end
17
+
18
+ describe '#follow' do
19
+ it 'should allow you to follow' do
20
+ @usera.follow(@userb)
21
+
22
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
23
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
24
+ end
25
+
26
+ it 'should not allow you to follow yourself' do
27
+ @usera.follow(@usera)
28
+
29
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
30
+ end
31
+
32
+ it 'should add each individual to the reciprocated set if you both follow each other' do
33
+ @usera.follow(@userb)
34
+ @userb.follow(@usera)
35
+
36
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
37
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
38
+ end
39
+ describe "with non-id key" do
40
+ it 'should allow you to follow' do
41
+ @usera.follow(@admin)
42
+
43
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
44
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@admin.send(@admin.class.amico_key)}").should be(1)
45
+ end
46
+
47
+ it 'should add each individual to the reciprocated set if you both follow each other' do
48
+ @usera.follow(@admin)
49
+ @admin.follow(@usera)
50
+
51
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
52
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@admin.send(@admin.class.amico_key)}").should be(1)
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ describe '#unfollow' do
59
+ it 'should allow you to unfollow' do
60
+ @usera.follow(@userb)
61
+
62
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
63
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
64
+
65
+ @usera.unfollow(@userb)
66
+
67
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
68
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
69
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
70
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
71
+ end
72
+
73
+ describe "non-id key" do
74
+ it 'should allow you to unfollow' do
75
+ @usera.follow(@admin)
76
+
77
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
78
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@admin.send(@admin.class.amico_key)}").should be(1)
79
+
80
+ @usera.unfollow(@admin)
81
+
82
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
83
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@admin.send(@admin.class.amico_key)}").should be(0)
84
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
85
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@admin.send(@admin.class.amico_key)}").should be(0)
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '#block' do
91
+ it 'should allow you to block someone following you' do
92
+ @userb.follow(@usera)
93
+ @usera.block(@userb)
94
+
95
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
96
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
97
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
98
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
99
+ end
100
+
101
+ it 'should allow you to block someone who is not following you' do
102
+ @usera.block(@userb)
103
+
104
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
105
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
106
+ end
107
+
108
+ it 'should not allow someone you have blocked to follow you' do
109
+ @usera.block(@userb)
110
+
111
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
112
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
113
+
114
+ @userb.follow(@usera)
115
+
116
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
117
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
118
+ end
119
+
120
+ it 'should not allow you to block yourself' do
121
+ @usera.block(@usera)
122
+ @usera.blocked?(@usera).should be_false
123
+ end
124
+ describe "non-id key" do
125
+ it 'should allow you to block someone following you' do
126
+ @admin.follow(@usera)
127
+ @usera.block(@admin)
128
+
129
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@admin.class.amico_key)}").should be(0)
130
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
131
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
132
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@admin.class.amico_key)}").should be(0)
133
+ end
134
+
135
+ it 'should allow you to block someone who is not following you' do
136
+ @usera.block(@userb)
137
+
138
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@admin.class.amico_key)}").should be(0)
139
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
140
+ end
141
+
142
+ it 'should not allow someone you have blocked to follow you' do
143
+ @usera.block(@admin)
144
+
145
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@admin.class.amico_key)}").should be(0)
146
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
147
+
148
+ @admin.follow(@usera)
149
+
150
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@admin.class.amico_key)}").should be(0)
151
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
152
+ end
153
+
154
+ end
155
+ end
156
+
157
+ describe '#unblock' do
158
+ it 'should allow you to unblock someone you have blocked' do
159
+ @usera.block(@userb)
160
+ @usera.blocked?(@userb).should be_true
161
+ @usera.unblock(@userb)
162
+ @usera.blocked?(@userb).should be_false
163
+ end
164
+ it 'should allow you to unblock someone you have blocked with non-id keys' do
165
+ @usera.block(@admin)
166
+ @usera.blocked?(@admin).should be_true
167
+ @usera.unblock(@admin)
168
+ @usera.blocked?(@admin).should be_false
169
+ end
170
+ end
171
+
172
+ describe "destructive methods named with ! bang" do
173
+ describe '#follow' do
174
+ it 'should allow you to follow' do
175
+ @usera.follow!(@userb)
176
+
177
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
178
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
179
+ end
180
+
181
+ it 'should not allow you to follow yourself' do
182
+ @usera.follow!(@usera)
183
+
184
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
185
+ end
186
+
187
+ it 'should add each individual to the reciprocated set if you both follow each other' do
188
+ @usera.follow!(@userb)
189
+ @userb.follow!(@usera)
190
+
191
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
192
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
193
+ end
194
+ end
195
+
196
+ describe '#unfollow' do
197
+ it 'should allow you to unfollow' do
198
+ @usera.follow!(@userb)
199
+
200
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
201
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
202
+
203
+ @usera.unfollow!(@userb)
204
+
205
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
206
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
207
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
208
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
209
+ end
210
+ end
211
+ describe '#block!' do
212
+ it 'should allow you to block someone following you' do
213
+ @userb.follow(@usera)
214
+ @usera.block!(@userb)
215
+
216
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
217
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
218
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
219
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.reciprocated_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
220
+ end
221
+
222
+ it 'should allow you to block someone who is not following you' do
223
+ @usera.block!(@userb)
224
+
225
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
226
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
227
+ end
228
+
229
+ it 'should not allow someone you have blocked to follow you' do
230
+ @usera.block!(@userb)
231
+
232
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
233
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
234
+
235
+ @userb.follow!(@usera)
236
+
237
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
238
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.blocked_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(1)
239
+ end
240
+
241
+ it 'should not allow you to block yourself' do
242
+ @usera.block!(@usera)
243
+ @usera.blocked?(@usera).should be_false
244
+ end
245
+ end
246
+ describe '#unblock!' do
247
+ it 'should allow you to unblock someone you have blocked' do
248
+ @usera.block!(@userb)
249
+ @usera.blocked?(@userb).should be_true
250
+ @usera.unblock!(@userb)
251
+ @usera.blocked?(@userb).should be_false
252
+ end
253
+ end
254
+
255
+ end
256
+
257
+ describe '#following?' do
258
+ it 'should return that you are following' do
259
+ @usera.follow(@userb)
260
+ @usera.following?(@userb).should be_true
261
+ @userb.following?(@usera).should be_false
262
+
263
+ @userb.follow(@usera)
264
+ @userb.following?(@usera).should be_true
265
+ end
266
+ describe "non-id keys" do
267
+ it 'should return that you are following' do
268
+ @usera.follow(@admin)
269
+ @usera.following?(@admin).should be_true
270
+ @admin.following?(@usera).should be_false
271
+
272
+ @admin.follow(@usera)
273
+ @admin.following?(@usera).should be_true
274
+ end
275
+ end
276
+ end
277
+
278
+ describe '#follower?' do
279
+ it 'should return that you are being followed' do
280
+ @userb.follow(@usera)
281
+ @usera.follower?(@userb).should be_true
282
+ @userb.follower?(@usera).should be_false
283
+
284
+ @usera.follow(@userb)
285
+ @userb.follower?(@usera).should be_true
286
+ end
287
+ describe "non-id keys" do
288
+ it 'should return that you are being followed' do
289
+ @admin.follow(@usera)
290
+ @usera.follower?(@admin).should be_true
291
+ @admin.follower?(@usera).should be_false
292
+
293
+ @usera.follow(@admin)
294
+ @admin.follower?(@usera).should be_true
295
+ end
296
+ end
297
+ end
298
+
299
+ describe '#blocked?' do
300
+ it 'should return that someone is being blocked' do
301
+ @usera.block(@userb)
302
+ @usera.blocked?(@userb).should be_true
303
+ @userb.following?(@usera).should be_false
304
+ end
305
+ describe "non-id keys" do
306
+ it 'should return that someone is being blocked' do
307
+ @usera.block(@admin)
308
+ @usera.blocked?(@admin).should be_true
309
+ @admin.following?(@usera).should be_false
310
+ end
311
+ end
312
+ end
313
+
314
+ describe '#reciprocated?' do
315
+ it 'should return true if both individuals are following each other' do
316
+ @usera.follow(@userb)
317
+ @userb.follow(@usera)
318
+ @usera.reciprocated?(@userb).should be_true
319
+ end
320
+
321
+ it 'should return false if both individuals are not following each other' do
322
+ @usera.follow(@userb)
323
+ @usera.reciprocated?(@userb).should be_false
324
+ end
325
+ describe "non-id keys" do
326
+ it 'should return true if both individuals are following each other' do
327
+ @usera.follow(@admin)
328
+ @admin.follow(@usera)
329
+ @usera.reciprocated?(@admin).should be_true
330
+ end
331
+
332
+ it 'should return false if both individuals are not following each other' do
333
+ @usera.follow(@admin)
334
+ @usera.reciprocated?(@admin).should be_false
335
+ end
336
+ end
337
+ end
338
+
339
+ describe '#following' do
340
+ it 'should return the correct list' do
341
+ userc = Factory :user
342
+ @usera.follow(@userb)
343
+ @usera.follow(userc)
344
+ @usera.following.should eql(["#{userc.id}", "#{@userb.send(@userb.class.amico_key)}"])
345
+ @usera.following(:page => 5).should eql(["#{userc.id}", "#{@userb.send(@userb.class.amico_key)}"])
346
+ end
347
+
348
+ it 'should page correctly' do
349
+ user = add_reciprocal_followers
350
+
351
+ user.following(:page => 1, :page_size => 5).size.should be(5)
352
+ user.following(:page => 1, :page_size => 10).size.should be(10)
353
+ user.following(:page => 1, :page_size => 25).size.should be(25)
354
+ end
355
+ describe "non-id keys" do
356
+ it 'should return the correct list' do
357
+ userc = Factory :user
358
+ @usera.follow(@admin)
359
+ @usera.follow(userc)
360
+ @usera.following.should =~ ["#{userc.id}", "#{@admin.send(@admin.class.amico_key)}"]
361
+ @usera.following(:page => 5).should =~ ["#{userc.id}", "#{@admin.send(@admin.class.amico_key)}"]
362
+ end
363
+ end
364
+ end
365
+
366
+ describe '#followers' do
367
+ it 'should return the correct list' do
368
+ userc = Factory :user
369
+ @usera.follow(@userb)
370
+ userc.follow(@userb)
371
+ @userb.followers.should eql(["#{userc.id}", "#{@usera.send(@usera.class.amico_key)}"])
372
+ @userb.followers(:page => 5).should eql(["#{userc.id}", "#{@usera.send(@usera.class.amico_key)}"])
373
+ end
374
+
375
+ it 'should page correctly' do
376
+ user = add_reciprocal_followers
377
+
378
+ user.followers(:page => 1, :page_size => 5).size.should be(5)
379
+ user.followers(:page => 1, :page_size => 10).size.should be(10)
380
+ user.followers(:page => 1, :page_size => 25).size.should be(25)
381
+ end
382
+ describe "non-id keys" do
383
+ it 'should return the correct list' do
384
+ userc = Factory :user
385
+ @usera.follow(@admin)
386
+ userc.follow(@admin)
387
+ @admin.followers.should eql(["#{userc.id}", "#{@usera.send(@usera.class.amico_key)}"])
388
+ @admin.followers(:page => 5).should eql(["#{userc.id}", "#{@usera.send(@usera.class.amico_key)}"])
389
+ end
390
+ end
391
+ end
392
+
393
+ describe '#blocked' do
394
+ it 'should return the correct list' do
395
+ userc = Factory :user
396
+ @usera.block(@userb)
397
+ @usera.block(userc)
398
+ @usera.blocked.should eql(["#{userc.id}", "#{@userb.send(@userb.class.amico_key)}"])
399
+ @usera.blocked(:page => 5).should eql(["#{userc.id}", "#{@userb.send(@userb.class.amico_key)}"])
400
+ end
401
+
402
+ it 'should page correctly' do
403
+ user = add_reciprocal_followers(26, true)
404
+
405
+ user.blocked(:page => 1, :page_size => 5).size.should be(5)
406
+ user.blocked(:page => 1, :page_size => 10).size.should be(10)
407
+ user.blocked(:page => 1, :page_size => 25).size.should be(25)
408
+ end
409
+ describe "non-id keys" do
410
+ it 'should return the correct list' do
411
+ userc = Factory :user
412
+ @usera.block(@admin)
413
+ @usera.block(userc)
414
+ @usera.blocked.should =~ ["#{userc.id}", "#{@admin.send(@admin.class.amico_key)}"]
415
+ @usera.blocked(:page => 5).should =~ ["#{userc.id}", "#{@admin.send(@admin.class.amico_key)}"]
416
+ end
417
+ end
418
+ end
419
+
420
+ describe '#reciprocated' do
421
+ it 'should return the correct list' do
422
+ @usera.follow(@userb)
423
+ @userb.follow(@usera)
424
+ @usera.reciprocated.should eql(["#{@userb.send(@userb.class.amico_key)}"])
425
+ @userb.reciprocated.should eql(["#{@usera.send(@usera.class.amico_key)}"])
426
+ end
427
+
428
+ it 'should page correctly' do
429
+ user = add_reciprocal_followers
430
+
431
+ user.reciprocated(:page => 1, :page_size => 5).size.should be(5)
432
+ user.reciprocated(:page => 1, :page_size => 10).size.should be(10)
433
+ user.reciprocated(:page => 1, :page_size => 25).size.should be(25)
434
+ end
435
+ describe "non-id keys" do
436
+ it 'should return the correct list' do
437
+ @usera.follow(@admin)
438
+ @admin.follow(@usera)
439
+ @usera.reciprocated.should eql(["#{@admin.send(@admin.class.amico_key)}"])
440
+ @admin.reciprocated.should eql(["#{@usera.send(@usera.class.amico_key)}"])
441
+ end
442
+ end
443
+ end
444
+
445
+ describe '#following_count' do
446
+ it 'should return the correct count' do
447
+ @usera.follow(@userb)
448
+ @usera.following_count.should be(1)
449
+ end
450
+ it 'should return the correct count for non-id keys' do
451
+ @usera.follow(@admin)
452
+ @usera.following_count.should be(1)
453
+ end
454
+ end
455
+
456
+ describe '#followers_count' do
457
+ it 'should return the correct count' do
458
+ @usera.follow(@userb)
459
+ @userb.followers_count.should be(1)
460
+ end
461
+ it 'should return the correct count for non-id keys' do
462
+ @usera.follow(@admin)
463
+ @admin.followers_count.should be(1)
464
+ end
465
+ end
466
+
467
+ describe '#blocked_count' do
468
+ it 'should return the correct count' do
469
+ @usera.block(@userb)
470
+ @usera.blocked_count.should be(1)
471
+ end
472
+ it 'should return the correct count for non-id keys' do
473
+ @usera.block(@admin)
474
+ @usera.blocked_count.should be(1)
475
+ end
476
+ end
477
+
478
+ describe '#reciprocated_count' do
479
+ it 'should return the correct count' do
480
+ userc = Factory :user
481
+ userd = Factory :user
482
+ @usera.follow(@userb)
483
+ @userb.follow(@usera)
484
+ @usera.follow(userc)
485
+ userc.follow(@usera)
486
+ @usera.follow(userd)
487
+ @usera.reciprocated_count.should be(2)
488
+ end
489
+ it 'should return the correct count for non-id keys' do
490
+ userc = Factory :user
491
+ userd = Factory :user
492
+ @usera.follow(@admin)
493
+ @admin.follow(@usera)
494
+ @usera.follow(userc)
495
+ userc.follow(@usera)
496
+ @usera.follow(userd)
497
+ @usera.reciprocated_count.should be(2)
498
+ end
499
+ end
500
+
501
+ describe 'pending_follow enabled' do
502
+ before(:each) do
503
+ Amico.pending_follow = true
504
+ end
505
+
506
+ after(:each) do
507
+ Amico.pending_follow = false
508
+ end
509
+
510
+ describe '#follow' do
511
+ it 'should allow you to follow but the relationship is initially pending' do
512
+ @usera.follow(@userb)
513
+
514
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
515
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
516
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.pending_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
517
+ end
518
+
519
+ it 'should remove the pending relationship if you have a pending follow, but you unfollow' do
520
+ @usera.follow(@userb)
521
+
522
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
523
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
524
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.pending_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(1)
525
+
526
+ @usera.unfollow(@userb)
527
+
528
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.following_key}:#{Amico.default_scope_key}:#{@usera.send(@usera.class.amico_key)}").should be(0)
529
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.followers_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
530
+ Amico.redis.zcard("#{Amico.namespace}:#{Amico.pending_key}:#{Amico.default_scope_key}:#{@userb.send(@userb.class.amico_key)}").should be(0)
531
+ end
532
+
533
+ describe 'removing the pending relationship and add to following and followers if #accept is called' do
534
+ it "should work with non-bang-named methods" do
535
+ @usera.follow(@userb)
536
+ @usera.pending?(@userb).should be_true
537
+
538
+ @usera.accept(@userb)
539
+
540
+ @usera.pending?(@userb).should be_false
541
+ @usera.following?(@userb).should be_true
542
+ @userb.following?(@usera).should be_false
543
+ @userb.follower?(@usera).should be_true
544
+ @usera.follower?(@userb).should be_false
545
+ end
546
+ it "should work with ! bang-named methods" do
547
+ @usera.follow!(@userb)
548
+ @usera.pending?(@userb).should be_true
549
+
550
+ @usera.accept!(@userb)
551
+
552
+ @usera.pending?(@userb).should be_false
553
+ @usera.following?(@userb).should be_true
554
+ @userb.following?(@usera).should be_false
555
+ @userb.follower?(@usera).should be_true
556
+ @usera.follower?(@userb).should be_false
557
+ end
558
+ end
559
+
560
+ describe 'removing the pending relationship and add to following and followers if #accept is called and add to reciprocated relationship' do
561
+ it "should work with non-bang-named methods" do
562
+ @usera.follow(@userb)
563
+ @userb.follow(@usera)
564
+ @usera.pending?(@userb).should be_true
565
+ @userb.pending?(@usera).should be_true
566
+
567
+ @usera.accept(@userb)
568
+
569
+ @usera.pending?(@userb).should be_false
570
+ @userb.pending?(@usera).should be_true
571
+ @usera.following?(@userb).should be_true
572
+ @userb.following?(@usera).should be_false
573
+ @userb.follower?(@usera).should be_true
574
+ @usera.follower?(@userb).should be_false
575
+
576
+ @userb.accept(@usera)
577
+
578
+ @usera.pending?(@userb).should be_false
579
+ @userb.pending?(@usera).should be_false
580
+ @usera.following?(@userb).should be_true
581
+ @userb.following?(@usera).should be_true
582
+ @userb.follower?(@usera).should be_true
583
+ @usera.follower?(@userb).should be_true
584
+ @usera.reciprocated?(@userb).should be_true
585
+ end
586
+ it "should work with ! bang-named methods" do
587
+ @usera.follow!(@userb)
588
+ @userb.follow!(@usera)
589
+ @usera.pending?(@userb).should be_true
590
+ @userb.pending?(@usera).should be_true
591
+
592
+ @usera.accept!(@userb)
593
+
594
+ @usera.pending?(@userb).should be_false
595
+ @userb.pending?(@usera).should be_true
596
+ @usera.following?(@userb).should be_true
597
+ @userb.following?(@usera).should be_false
598
+ @userb.follower?(@usera).should be_true
599
+ @usera.follower?(@userb).should be_false
600
+
601
+ @userb.accept!(@usera)
602
+
603
+ @usera.pending?(@userb).should be_false
604
+ @userb.pending?(@usera).should be_false
605
+ @usera.following?(@userb).should be_true
606
+ @userb.following?(@usera).should be_true
607
+ @userb.follower?(@usera).should be_true
608
+ @usera.follower?(@userb).should be_true
609
+ @usera.reciprocated?(@userb).should be_true
610
+ end
611
+ end
612
+ end
613
+
614
+ describe '#block' do
615
+ it 'should remove the pending relationship if you block someone' do
616
+ @userb.follow(@usera)
617
+ @userb.pending?(@usera).should be_true
618
+ @usera.block(@userb)
619
+ @userb.pending?(@usera).should be_false
620
+ @usera.blocked?(@userb).should be_true
621
+ end
622
+ end
623
+
624
+ describe '#pending' do
625
+ it 'should return the correct list' do
626
+ @usera.follow(@userb)
627
+ @userb.follow(@usera)
628
+ @usera.pending.should eql(["#{@userb.send(@userb.class.amico_key)}"])
629
+ @userb.pending.should eql(["#{@usera.send(@usera.class.amico_key)}"])
630
+ end
631
+
632
+ it 'should page correctly' do
633
+ user = add_reciprocal_followers
634
+
635
+ user.pending(:page => 1, :page_size => 5).size.should be(5)
636
+ user.pending(:page => 1, :page_size => 10).size.should be(10)
637
+ user.pending(:page => 1, :page_size => 25).size.should be(25)
638
+ end
639
+ end
640
+
641
+ describe '#pending_count' do
642
+ it 'should return the correct count' do
643
+ userc = Factory :user
644
+ userd = Factory :user
645
+ @usera.follow(@userb)
646
+ @userb.follow(@usera)
647
+ @usera.follow(userc)
648
+ userc.follow(@usera)
649
+ @usera.follow(userd)
650
+ @usera.pending_count.should be(2)
651
+ end
652
+ end
653
+
654
+ describe '#pending_page_count' do
655
+ it 'should return the correct count' do
656
+ user = add_reciprocal_followers
657
+
658
+ user.pending_page_count.should be(2)
659
+ user.pending_page_count( 10).should be(3)
660
+ user.pending_page_count( 5).should be(6)
661
+ user.pending_page_count(2).should be(13)
662
+ end
663
+ end
664
+ end
665
+
666
+ describe 'scope' do
667
+ it 'should allow you to scope a call to follow a different thing' do
668
+ Amico.default_scope_key = 'user'
669
+ @usera.follow(@userb, 'user')
670
+ @usera.following?(@userb).should be_true
671
+ @usera.following?(@userb, 'user').should be_true
672
+ @usera.following.should eql(["#{@userb.send(@userb.class.amico_key)}"])
673
+ @usera.following( {:page_size => Amico.page_size, :page => 1}, 'user').should eql(["#{@userb.send(@userb.class.amico_key)}"])
674
+ @usera.following?(@userb, 'project').should be_false
675
+ @usera.follow(@userb, 'project')
676
+ @usera.following?(@userb, 'project').should be_true
677
+ @usera.following( {:page_size => Amico.page_size, :page => 1}, 'project').should eql(["#{@userb.send(@userb.class.amico_key)}"])
678
+ end
679
+ end
680
+
681
+ private
682
+
683
+ def add_reciprocal_followers(count = 26, block_relationship = false)
684
+ outer_user = nil
685
+ 1.upto(count) do
686
+ outer_user = Factory :user
687
+ 1.upto(count) do
688
+ inner_user = Factory :user
689
+ outer_user.follow! inner_user
690
+ inner_user.follow! outer_user
691
+ if block_relationship
692
+ outer_user.block! inner_user
693
+ inner_user.block! outer_user
694
+ end
695
+ end
696
+ end
697
+ outer_user
698
+ end
699
+ end
700
+ end