acts_as_amico 0.1.0

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.
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