socialization 1.1.0 → 1.2.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +2 -1
  4. data/Appraisals +13 -1
  5. data/CHANGELOG.md +12 -0
  6. data/Guardfile +12 -0
  7. data/LICENSE +2 -2
  8. data/README.md +46 -1
  9. data/Rakefile +8 -10
  10. data/lib/socialization/stores/active_record/follow.rb +4 -0
  11. data/lib/socialization/stores/active_record/like.rb +4 -0
  12. data/lib/socialization/stores/active_record/mention.rb +4 -0
  13. data/lib/socialization/stores/active_record/mixins/base.rb +4 -0
  14. data/lib/socialization/stores/mixins/follow.rb +1 -1
  15. data/lib/socialization/version.rb +1 -1
  16. data/socialization.gemspec +5 -3
  17. data/spec/actors/follower_spec.rb +113 -0
  18. data/spec/actors/liker_spec.rb +105 -0
  19. data/spec/actors/mentioner_spec.rb +105 -0
  20. data/spec/spec_helper.rb +21 -0
  21. data/{test/test_helper.rb → spec/spec_support/data_stores.rb} +76 -81
  22. data/spec/spec_support/matchers.rb +54 -0
  23. data/spec/stores/active_record/follow_store_spec.rb +147 -0
  24. data/spec/stores/active_record/like_store_spec.rb +146 -0
  25. data/spec/stores/active_record/mention_store_spec.rb +148 -0
  26. data/spec/stores/active_record/mixins/base_spec.rb +25 -0
  27. data/spec/stores/redis/base_spec.rb +195 -0
  28. data/spec/stores/redis/config_spec.rb +28 -0
  29. data/spec/stores/redis/follow_store_spec.rb +26 -0
  30. data/spec/stores/redis/like_store_spec.rb +23 -0
  31. data/spec/stores/redis/mention_store_spec.rb +23 -0
  32. data/spec/string_spec.rb +13 -0
  33. data/spec/victims/followable_spec.rb +59 -0
  34. data/spec/victims/likeable_spec.rb +58 -0
  35. data/spec/victims/mentionable_spec.rb +59 -0
  36. data/spec/world_spec.rb +107 -0
  37. metadata +79 -42
  38. data/test/actors/follower_test.rb +0 -114
  39. data/test/actors/liker_test.rb +0 -106
  40. data/test/actors/mentioner_test.rb +0 -106
  41. data/test/stores/active_record/follow_store_test.rb +0 -138
  42. data/test/stores/active_record/like_store_test.rb +0 -139
  43. data/test/stores/active_record/mention_store_test.rb +0 -138
  44. data/test/stores/redis/base_test.rb +0 -203
  45. data/test/stores/redis/config_test.rb +0 -30
  46. data/test/stores/redis/follow_store_test.rb +0 -27
  47. data/test/stores/redis/like_store_test.rb +0 -25
  48. data/test/stores/redis/mention_store_test.rb +0 -25
  49. data/test/string_test.rb +0 -13
  50. data/test/victims/followable_test.rb +0 -60
  51. data/test/victims/likeable_test.rb +0 -60
  52. data/test/victims/mentionable_test.rb +0 -60
  53. data/test/world_test.rb +0 -112
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialization::ActiveRecordStores::Like do
4
+ before do
5
+ @klass = Socialization::ActiveRecordStores::Like
6
+ @klass.touch nil
7
+ @klass.after_like nil
8
+ @klass.after_unlike nil
9
+ @liker = ImALiker.create
10
+ @likeable = ImALikeable.create
11
+ end
12
+
13
+ describe "data store" do
14
+ it "inherits Socialization::ActiveRecordStores::Like" do
15
+ expect(Socialization.like_model).to eq Socialization::ActiveRecordStores::Like
16
+ end
17
+ end
18
+
19
+ describe "#like!" do
20
+ it "creates a Like record" do
21
+ @klass.like!(@liker, @likeable)
22
+ expect(@liker).to match_liker @klass.last
23
+ expect(@likeable).to match_likeable @klass.last
24
+ end
25
+
26
+ it "increments counter caches" do
27
+ liker = ImALikerWithCounterCache.create
28
+ likeable = ImALikeableWithCounterCache.create
29
+ @klass.like!(liker, likeable)
30
+ expect(liker.reload.likees_count).to eq(1)
31
+ expect(likeable.reload.likers_count).to eq(1)
32
+ end
33
+
34
+ it "touches liker when instructed" do
35
+ @klass.touch :liker
36
+ expect(@liker).to receive(:touch).once
37
+ expect(@likeable).to receive(:touch).never
38
+ @klass.like!(@liker, @likeable)
39
+ end
40
+
41
+ it "touches likeable when instructed" do
42
+ @klass.touch :likeable
43
+ expect(@liker).to receive(:touch).never
44
+ expect(@likeable).to receive(:touch).once
45
+ @klass.like!(@liker, @likeable)
46
+ end
47
+
48
+ it "touches all when instructed" do
49
+ @klass.touch :all
50
+ expect(@liker).to receive(:touch).once
51
+ expect(@likeable).to receive(:touch).once
52
+ @klass.like!(@liker, @likeable)
53
+ end
54
+
55
+ it "calls after like hook" do
56
+ @klass.after_like :after_like
57
+ expect(@klass).to receive(:after_like).once
58
+ @klass.like!(@liker, @likeable)
59
+ end
60
+
61
+ it "calls after unlike hook" do
62
+ @klass.after_like :after_unlike
63
+ expect(@klass).to receive(:after_unlike).once
64
+ @klass.like!(@liker, @likeable)
65
+ end
66
+ end
67
+
68
+ describe "#unlike!" do
69
+ it "decrements counter caches" do
70
+ liker = ImALikerWithCounterCache.create
71
+ likeable = ImALikeableWithCounterCache.create
72
+ @klass.like!(liker, likeable)
73
+ @klass.unlike!(liker, likeable)
74
+ expect(liker.reload.likees_count).to eq 0
75
+ expect(likeable.reload.likers_count).to eq 0
76
+ end
77
+ end
78
+
79
+ describe "#likes?" do
80
+ it "returns true when like exists" do
81
+ @klass.create! do |f|
82
+ f.liker = @liker
83
+ f.likeable = @likeable
84
+ end
85
+ expect(@klass.likes?(@liker, @likeable)).to be true
86
+ end
87
+
88
+ it "returns false when like doesn't exist" do
89
+ expect(@klass.likes?(@liker, @likeable)).to be false
90
+ end
91
+ end
92
+
93
+ describe "#likers" do
94
+ it "returns an array of likers" do
95
+ liker1 = ImALiker.create
96
+ liker2 = ImALiker.create
97
+ liker1.like!(@likeable)
98
+ liker2.like!(@likeable)
99
+ expect(@klass.likers(@likeable, liker1.class)).to eq [liker1, liker2]
100
+ end
101
+
102
+ it "returns an array of liker ids when plucking" do
103
+ liker1 = ImALiker.create
104
+ liker2 = ImALiker.create
105
+ liker1.like!(@likeable)
106
+ liker2.like!(@likeable)
107
+ expect(@klass.likers(@likeable, liker1.class, :pluck => :id)).to eq [liker1.id, liker2.id]
108
+ end
109
+ end
110
+
111
+ describe "#likeables" do
112
+ it "returns an array of likers" do
113
+ likeable1 = ImALikeable.create
114
+ likeable2 = ImALikeable.create
115
+ @liker.like!(likeable1)
116
+ @liker.like!(likeable2)
117
+ expect(@klass.likeables(@liker, likeable1.class)).to eq [likeable1, likeable2]
118
+ end
119
+
120
+ it "returns an array of liker ids when plucking" do
121
+ likeable1 = ImALikeable.create
122
+ likeable2 = ImALikeable.create
123
+ @liker.like!(likeable1)
124
+ @liker.like!(likeable2)
125
+ expect(@klass.likeables(@liker, likeable1.class, :pluck => :id)).to eq [likeable1.id, likeable2.id]
126
+ end
127
+ end
128
+
129
+ describe "#remove_likers" do
130
+ it "deletes all likers relationships for a likeable" do
131
+ @liker.like!(@likeable)
132
+ expect(@likeable.likers(@liker.class).count).to eq 1
133
+ @klass.remove_likers(@likeable)
134
+ expect(@likeable.likers(@liker.class).count).to eq 0
135
+ end
136
+ end
137
+
138
+ describe "#remove_likeables" do
139
+ it "deletes all likeables relationships for a liker" do
140
+ @liker.like!(@likeable)
141
+ expect(@liker.likeables(@likeable.class).count).to eq 1
142
+ @klass.remove_likeables(@liker)
143
+ expect(@liker.likeables(@likeable.class).count).to eq 0
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialization::ActiveRecordStores::Mention do
4
+ before do
5
+ @klass = Socialization::ActiveRecordStores::Mention
6
+ @klass.touch nil
7
+ @klass.after_mention nil
8
+ @klass.after_unmention nil
9
+ @mentioner = ImAMentioner.create
10
+ @mentionable = ImAMentionable.create
11
+ end
12
+
13
+ describe "data store" do
14
+ it "inherits Socialization::ActiveRecordStores::Mention" do
15
+ expect(Socialization.mention_model).to eq Socialization::ActiveRecordStores::Mention
16
+ end
17
+ end
18
+
19
+ describe "#mention!" do
20
+ it "creates a Mention record" do
21
+ @klass.mention!(@mentioner, @mentionable)
22
+ expect(@mentioner).to match_mentioner(@klass.last)
23
+ expect(@mentionable).to match_mentionable(@klass.last)
24
+ end
25
+
26
+ it "increments counter caches" do
27
+ mentioner = ImAMentionerWithCounterCache.create
28
+ mentionable = ImAMentionableWithCounterCache.create
29
+ @klass.mention!(mentioner, mentionable)
30
+ expect(mentioner.reload.mentionees_count).to eq 1
31
+ expect(mentionable.reload.mentioners_count).to eq 1
32
+ end
33
+
34
+ it "touchs mentioner when instructed" do
35
+ @klass.touch :mentioner
36
+ expect(@mentioner).to receive(:touch).once
37
+ expect(@mentionable).to receive(:touch).never
38
+ @klass.mention!(@mentioner, @mentionable)
39
+ end
40
+
41
+ it "touchs mentionable when instructed" do
42
+ @klass.touch :mentionable
43
+ expect(@mentioner).to receive(:touch).never
44
+ expect(@mentionable).to receive(:touch).once
45
+ @klass.mention!(@mentioner, @mentionable)
46
+ end
47
+
48
+ it "touchs all when instructed" do
49
+ @klass.touch :all
50
+ expect(@mentioner).to receive(:touch).once
51
+ expect(@mentionable).to receive(:touch).once
52
+ @klass.mention!(@mentioner, @mentionable)
53
+ end
54
+
55
+ it "calls after mention hook" do
56
+ @klass.after_mention :after_mention
57
+ expect(@klass).to receive(:after_mention).once
58
+ @klass.mention!(@mentioner, @mentionable)
59
+ end
60
+
61
+ it "calls after unmention hook" do
62
+ @klass.after_mention :after_unmention
63
+ expect(@klass).to receive(:after_unmention).once
64
+ @klass.mention!(@mentioner, @mentionable)
65
+ end
66
+ end
67
+
68
+ describe "#unmention!" do
69
+ it "decrements counter caches" do
70
+ mentioner = ImAMentionerWithCounterCache.create
71
+ mentionable = ImAMentionableWithCounterCache.create
72
+ @klass.mention!(mentioner, mentionable)
73
+ @klass.unmention!(mentioner, mentionable)
74
+ expect(mentioner.reload.mentionees_count).to eq 0
75
+ expect(mentionable.reload.mentioners_count).to eq 0
76
+ end
77
+ end
78
+
79
+
80
+ describe "#mentions?" do
81
+ it "returns true when mention exists" do
82
+ @klass.create! do |f|
83
+ f.mentioner = @mentioner
84
+ f.mentionable = @mentionable
85
+ end
86
+ expect(@klass.mentions?(@mentioner, @mentionable)).to be true
87
+ end
88
+
89
+ it "returns false when mention doesn't exist" do
90
+ expect(@klass.mentions?(@mentioner, @mentionable)).to be false
91
+ end
92
+ end
93
+
94
+ describe "#mentioners" do
95
+ it "returns an array of mentioners" do
96
+ mentioner1 = ImAMentioner.create
97
+ mentioner2 = ImAMentioner.create
98
+ mentioner1.mention!(@mentionable)
99
+ mentioner2.mention!(@mentionable)
100
+ expect(@klass.mentioners(@mentionable, mentioner1.class)).to eq [mentioner1, mentioner2]
101
+ end
102
+
103
+ it "returns an array of mentioner ids when plucking" do
104
+ mentioner1 = ImAMentioner.create
105
+ mentioner2 = ImAMentioner.create
106
+ mentioner1.mention!(@mentionable)
107
+ mentioner2.mention!(@mentionable)
108
+ expect(@klass.mentioners(@mentionable, mentioner1.class, :pluck => :id)).to eq [mentioner1.id, mentioner2.id]
109
+ end
110
+ end
111
+
112
+ describe "#mentionables" do
113
+ it "returns an array of mentioners" do
114
+ mentionable1 = ImAMentionable.create
115
+ mentionable2 = ImAMentionable.create
116
+ @mentioner.mention!(mentionable1)
117
+ @mentioner.mention!(mentionable2)
118
+ expect(@klass.mentionables(@mentioner, mentionable1.class)).to eq [mentionable1, mentionable2]
119
+ end
120
+
121
+ it "returns an array of mentioner ids when plucking" do
122
+ mentionable1 = ImAMentionable.create
123
+ mentionable2 = ImAMentionable.create
124
+ @mentioner.mention!(mentionable1)
125
+ @mentioner.mention!(mentionable2)
126
+ expect(@klass.mentionables(@mentioner, mentionable1.class, :pluck => :id)).to eq [mentionable1.id, mentionable2.id]
127
+ end
128
+ end
129
+
130
+ describe "#remove_mentioners" do
131
+ it "deletes all mentioners relationships for a mentionable" do
132
+ @mentioner.mention!(@mentionable)
133
+ expect(@mentionable.mentioners(@mentioner.class).count).to eq 1
134
+ @klass.remove_mentioners(@mentionable)
135
+ expect(@mentionable.mentioners(@mentioner.class).count).to eq 0
136
+ end
137
+ end
138
+
139
+ describe "#remove_mentionables" do
140
+ it "deletes all mentionables relationships for a mentioner" do
141
+ @mentioner.mention!(@mentionable)
142
+ expect(@mentioner.mentionables(@mentionable.class).count).to eq 1
143
+ @klass.remove_mentionables(@mentioner)
144
+ expect(@mentioner.mentionables(@mentionable.class).count).to eq 0
145
+ end
146
+ end
147
+ end
148
+
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialization::ActiveRecordStores::Mixins::Base do
4
+ describe ".update_counter" do
5
+ it "increments counter cache if column exists" do
6
+ followable = ImAFollowableWithCounterCache.create
7
+
8
+ update_counter(followable, followers_count: +1)
9
+
10
+ expect(followable.reload.followers_count).to eq(1)
11
+ end
12
+
13
+ it "does not raise any errors if column doesn't exist" do
14
+ followable = ImAFollowable.create
15
+ update_counter(followable, followers_count: +1)
16
+ end
17
+ end
18
+
19
+ def update_counter(model, counter)
20
+ klass = Object.new
21
+ klass.extend(Socialization::ActiveRecordStores::Mixins::Base)
22
+ klass.update_counter(model, counter)
23
+ end
24
+ end
25
+
@@ -0,0 +1,195 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialization::RedisStores::Base do
4
+ # Testing through RedisStores::Follow for easy testing
5
+ before(:each) do
6
+ use_redis_store
7
+ @klass = Socialization::RedisStores::Follow
8
+ @klass.touch nil
9
+ @klass.after_follow nil
10
+ @klass.after_unfollow nil
11
+ @follower1 = ImAFollower.create
12
+ @follower2 = ImAFollower.create
13
+ @followable1 = ImAFollowable.create
14
+ @followable2 = ImAFollowable.create
15
+ end
16
+
17
+ describe "RedisStores::Base through RedisStores::Follow" do
18
+ describe "Stores" do
19
+ it "inherits Socialization::RedisStores::Follow" do
20
+ expect(Socialization.follow_model).to eq(Socialization::RedisStores::Follow)
21
+ end
22
+ end
23
+
24
+ describe "#follow!" do
25
+ it "creates follow records" do
26
+ @klass.follow!(@follower1, @followable1)
27
+ expect(Socialization.redis.smembers(forward_key(@followable1))).to match_array ["#{@follower1.class}:#{@follower1.id}"]
28
+ expect(Socialization.redis.smembers(backward_key(@follower1))).to match_array ["#{@followable1.class}:#{@followable1.id}"]
29
+
30
+ @klass.follow!(@follower2, @followable1)
31
+ expect(Socialization.redis.smembers(forward_key(@followable1))).to match_array ["#{@follower1.class}:#{@follower1.id}", "#{@follower2.class}:#{@follower2.id}"]
32
+ expect(Socialization.redis.smembers(backward_key(@follower1))).to match_array ["#{@followable1.class}:#{@followable1.id}"]
33
+ expect(Socialization.redis.smembers(backward_key(@follower2))).to match_array ["#{@followable1.class}:#{@followable1.id}"]
34
+ end
35
+
36
+ it "touches follower when instructed" do
37
+ @klass.touch :follower
38
+ expect(@follower1).to receive(:touch).once
39
+ expect(@followable1).to receive(:touch).never
40
+ @klass.follow!(@follower1, @followable1)
41
+ end
42
+
43
+ it "touches followable when instructed" do
44
+ @klass.touch :followable
45
+ expect(@follower1).to receive(:touch).never
46
+ expect(@followable1).to receive(:touch).once
47
+ @klass.follow!(@follower1, @followable1)
48
+ end
49
+
50
+ it "touches all when instructed" do
51
+ @klass.touch :all
52
+ expect(@follower1).to receive(:touch).once
53
+ expect(@followable1).to receive(:touch).once
54
+ @klass.follow!(@follower1, @followable1)
55
+ end
56
+
57
+ it "calls after follow hook" do
58
+ @klass.after_follow :after_follow
59
+ expect(@klass).to receive(:after_follow).once
60
+ @klass.follow!(@follower1, @followable1)
61
+ end
62
+
63
+ it "calls after unfollow hook" do
64
+ @klass.after_follow :after_unfollow
65
+ expect(@klass).to receive(:after_unfollow).once
66
+ @klass.follow!(@follower1, @followable1)
67
+ end
68
+ end
69
+
70
+ describe "#unfollow!" do
71
+ before(:each) do
72
+ @klass.follow!(@follower1, @followable1)
73
+ end
74
+
75
+ it "removes follow records" do
76
+ @klass.unfollow!(@follower1, @followable1)
77
+ expect(Socialization.redis.smembers(forward_key(@followable1))).to be_empty
78
+ expect(Socialization.redis.smembers(backward_key(@follower1))).to be_empty
79
+ end
80
+ end
81
+
82
+ describe "#follows?" do
83
+ it "returns true when follow exists" do
84
+ @klass.follow!(@follower1, @followable1)
85
+ expect(@klass.follows?(@follower1, @followable1)).to be true
86
+ end
87
+
88
+ it "returns false when follow doesn't exist" do
89
+ expect(@klass.follows?(@follower1, @followable1)).to be false
90
+ end
91
+ end
92
+
93
+ describe "#followers" do
94
+ it "returns an array of followers" do
95
+ follower1 = ImAFollower.create
96
+ follower2 = ImAFollower.create
97
+ follower1.follow!(@followable1)
98
+ follower2.follow!(@followable1)
99
+ expect(@klass.followers(@followable1, follower1.class)).to match_array [follower1, follower2]
100
+ end
101
+
102
+ it "returns an array of follower ids when plucking" do
103
+ follower1 = ImAFollower.create
104
+ follower2 = ImAFollower.create
105
+ follower1.follow!(@followable1)
106
+ follower2.follow!(@followable1)
107
+ expect(@klass.followers(@followable1, follower1.class, :pluck => :id)).to match_array ["#{follower1.id}", "#{follower2.id}"]
108
+ end
109
+ end
110
+
111
+ describe "#followables" do
112
+ it "returns an array of followables" do
113
+ followable1 = ImAFollowable.create
114
+ followable2 = ImAFollowable.create
115
+ @follower1.follow!(followable1)
116
+ @follower1.follow!(followable2)
117
+
118
+ expect(@klass.followables(@follower1, followable1.class)).to match_array [followable1, followable2]
119
+ end
120
+
121
+ it "returns an array of followables ids when plucking" do
122
+ followable1 = ImAFollowable.create
123
+ followable2 = ImAFollowable.create
124
+ @follower1.follow!(followable1)
125
+ @follower1.follow!(followable2)
126
+ expect(@klass.followables(@follower1, followable1.class, :pluck => :id)).to match_array ["#{followable1.id}", "#{followable2.id}"]
127
+ end
128
+ end
129
+
130
+ describe "#generate_forward_key" do
131
+ it "returns valid key when passed an object" do
132
+ expect(forward_key(@followable1)).to eq("Followers:#{@followable1.class.name}:#{@followable1.id}")
133
+ end
134
+
135
+ it "returns valid key when passed a String" do
136
+ expect(forward_key("Followable:1")).to eq("Followers:Followable:1")
137
+ end
138
+ end
139
+
140
+ describe "#generate_backward_key" do
141
+ it "returns valid key when passed an object" do
142
+ expect(backward_key(@follower1)).to eq("Followables:#{@follower1.class.name}:#{@follower1.id}")
143
+ end
144
+
145
+ it "returns valid key when passed a String" do
146
+ expect(backward_key("Follower:1")).to eq("Followables:Follower:1")
147
+ end
148
+ end
149
+
150
+ describe "#remove_followers" do
151
+ it "deletes all followers relationships for a followable" do
152
+ @follower1.follow!(@followable1)
153
+ @follower2.follow!(@followable1)
154
+ expect(@followable1.followers(@follower1.class).count).to eq(2)
155
+
156
+ @klass.remove_followers(@followable1)
157
+ expect(@followable1.followers(@follower1.class).count).to eq(0)
158
+ expect(Socialization.redis.smembers(forward_key(@followable1))).to be_empty
159
+ expect(Socialization.redis.smembers(backward_key(@follower1))).to be_empty
160
+ expect(Socialization.redis.smembers(backward_key(@follower2))).to be_empty
161
+ end
162
+ end
163
+
164
+ describe "#remove_followables" do
165
+ it "deletes all followables relationships for a follower" do
166
+ @follower1.follow!(@followable1)
167
+ @follower1.follow!(@followable2)
168
+ expect(@follower1.followables(@followable1.class).count).to eq(2)
169
+
170
+ @klass.remove_followables(@follower1)
171
+ expect(@follower1.followables(@followable1.class).count).to eq(0)
172
+ expect(Socialization.redis.smembers backward_key(@followable1)).to be_empty
173
+ expect(Socialization.redis.smembers backward_key(@follower2)).to be_empty
174
+ expect(Socialization.redis.smembers forward_key(@follower1)).to be_empty
175
+ end
176
+ end
177
+
178
+ describe "#key_type_to_type_names" do
179
+ it "returns the proper arrays" do
180
+ expect(@klass.send(:key_type_to_type_names, Socialization::RedisStores::Follow)).to eq(['follower', 'followable'])
181
+ expect(@klass.send(:key_type_to_type_names, Socialization::RedisStores::Mention)).to eq(['mentioner', 'mentionable'])
182
+ expect(@klass.send(:key_type_to_type_names, Socialization::RedisStores::Like)).to eq(['liker', 'likeable'])
183
+ end
184
+ end
185
+ end
186
+
187
+ # Helpers
188
+ def forward_key(followable)
189
+ Socialization::RedisStores::Follow.send(:generate_forward_key, followable)
190
+ end
191
+
192
+ def backward_key(follower)
193
+ Socialization::RedisStores::Follow.send(:generate_backward_key, follower)
194
+ end
195
+ end