Commit db7025249b45bdfc86b05f91e24b408ccfb46d79
1 parent
03abebca
Exists in
master
and in
22 other branches
profile-suggestions: create only a small and fixed number of suggestions
Showing
2 changed files
with
140 additions
and
73 deletions
Show diff stats
app/models/profile_suggestion.rb
... | ... | @@ -8,6 +8,10 @@ class ProfileSuggestion < ActiveRecord::Base |
8 | 8 | profile_suggestion.suggestion_type = self.suggestion.class.to_s |
9 | 9 | end |
10 | 10 | |
11 | + after_destroy do |profile_suggestion| | |
12 | + self.class.generate_profile_suggestions(profile_suggestion.person) | |
13 | + end | |
14 | + | |
11 | 15 | acts_as_having_settings :field => :categories |
12 | 16 | |
13 | 17 | validate :must_be_a_valid_category, :on => :create |
... | ... | @@ -50,11 +54,11 @@ class ProfileSuggestion < ActiveRecord::Base |
50 | 54 | communities_with_common_tags |
51 | 55 | ] |
52 | 56 | |
53 | - # Number of suggestions | |
54 | - N_SUGGESTIONS = 30 | |
57 | + # Number of suggestions by rule | |
58 | + SUGGESTIONS_BY_RULE = 10 | |
55 | 59 | |
56 | - # Number max of attempts | |
57 | - MAX_ATTEMPTS = N_SUGGESTIONS * 2 | |
60 | + # Minimum number of suggestions | |
61 | + MIN_LIMIT = 15 | |
58 | 62 | |
59 | 63 | # Number of friends in common |
60 | 64 | COMMON_FRIENDS = 2 |
... | ... | @@ -66,8 +70,12 @@ class ProfileSuggestion < ActiveRecord::Base |
66 | 70 | COMMON_TAGS = 2 |
67 | 71 | |
68 | 72 | def self.register_suggestions(person, suggested_profiles, rule) |
73 | + already_suggested_profiles = person.profile_suggestions.map(&:suggestion_id).join(',') | |
74 | + suggested_profiles = suggested_profiles.where("profiles.id NOT IN (#{already_suggested_profiles})") if already_suggested_profiles.present? | |
75 | + suggested_profiles = suggested_profiles.limit(SUGGESTIONS_BY_RULE) | |
76 | + return if suggested_profiles.blank? | |
69 | 77 | counter = rule.split(/.*_with_/).last |
70 | - suggested_profiles.find_each do |suggested_profile| | |
78 | + suggested_profiles.each do |suggested_profile| | |
71 | 79 | suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(suggested_profile.id) |
72 | 80 | suggestion.send(counter+'=', suggested_profile.common_count.to_i) |
73 | 81 | suggestion.save! |
... | ... | @@ -87,6 +95,7 @@ class ProfileSuggestion < ActiveRecord::Base |
87 | 95 | |
88 | 96 | def self.people_with_common_friends(person) |
89 | 97 | person_friends = person.friends.map(&:id) |
98 | + return [] if person_friends.blank? | |
90 | 99 | person.environment.people. |
91 | 100 | select("profiles.*, suggestions.count AS common_count"). |
92 | 101 | joins(" |
... | ... | @@ -100,6 +109,7 @@ class ProfileSuggestion < ActiveRecord::Base |
100 | 109 | |
101 | 110 | def self.people_with_common_communities(person) |
102 | 111 | person_communities = person.communities.map(&:id) |
112 | + return [] if person_communities.blank? | |
103 | 113 | person.environment.people. |
104 | 114 | select("profiles.*, suggestions.count AS common_count"). |
105 | 115 | joins(" |
... | ... | @@ -115,6 +125,7 @@ class ProfileSuggestion < ActiveRecord::Base |
115 | 125 | |
116 | 126 | def self.people_with_common_tags(person) |
117 | 127 | profile_tags = person.articles.select('tags.id').joins(:tags).map(&:id) |
128 | + return [] if profile_tags.blank? | |
118 | 129 | person.environment.people. |
119 | 130 | select("profiles.*, suggestions.count as common_count"). |
120 | 131 | joins(" |
... | ... | @@ -132,6 +143,7 @@ class ProfileSuggestion < ActiveRecord::Base |
132 | 143 | |
133 | 144 | def self.communities_with_common_friends(person) |
134 | 145 | person_friends = person.friends.map(&:id) |
146 | + return [] if person_friends.blank? | |
135 | 147 | person.environment.communities. |
136 | 148 | select("profiles.*, suggestions.count AS common_count"). |
137 | 149 | joins(" |
... | ... | @@ -147,6 +159,7 @@ class ProfileSuggestion < ActiveRecord::Base |
147 | 159 | |
148 | 160 | def self.communities_with_common_tags(person) |
149 | 161 | profile_tags = person.articles.select('tags.id').joins(:tags).map(&:id) |
162 | + return [] if profile_tags.blank? | |
150 | 163 | person.environment.communities. |
151 | 164 | select("profiles.*, suggestions.count AS common_count"). |
152 | 165 | joins(" |
... | ... | @@ -164,15 +177,17 @@ class ProfileSuggestion < ActiveRecord::Base |
164 | 177 | |
165 | 178 | def disable |
166 | 179 | self.enabled = false |
167 | - self.save | |
180 | + self.save! | |
181 | + self.class.generate_profile_suggestions(self.person) | |
168 | 182 | end |
169 | 183 | |
170 | 184 | def self.generate_all_profile_suggestions |
171 | 185 | Delayed::Job.enqueue(ProfileSuggestion::GenerateAllJob.new) unless ProfileSuggestion::GenerateAllJob.exists? |
172 | 186 | end |
173 | 187 | |
174 | - def self.generate_profile_suggestions(person_id) | |
175 | - Delayed::Job.enqueue ProfileSuggestionsJob.new(person_id) unless ProfileSuggestionsJob.exists?(person_id) | |
188 | + def self.generate_profile_suggestions(person, force = false) | |
189 | + return if person.profile_suggestions.enabled.count >= MIN_LIMIT && !force | |
190 | + Delayed::Job.enqueue ProfileSuggestionsJob.new(person.id) unless ProfileSuggestionsJob.exists?(person.id) | |
176 | 191 | end |
177 | 192 | |
178 | 193 | class GenerateAllJob |
... | ... | @@ -181,7 +196,7 @@ class ProfileSuggestion < ActiveRecord::Base |
181 | 196 | end |
182 | 197 | |
183 | 198 | def perform |
184 | - Person.find_each {|person| ProfileSuggestion.generate_profile_suggestions(person.id) } | |
199 | + Person.find_each {|person| ProfileSuggestion.generate_profile_suggestions(person) } | |
185 | 200 | end |
186 | 201 | end |
187 | 202 | ... | ... |
test/unit/profile_suggestion_test.rb
... | ... | @@ -221,84 +221,136 @@ class ProfileSuggestionTest < ActiveSupport::TestCase |
221 | 221 | ProfileSuggestion.calculate_suggestions(person) |
222 | 222 | end |
223 | 223 | |
224 | - should 'update existing person suggestion when the number of common friends increase' do | |
225 | - suggested_person = create_user('test_user').person | |
226 | - suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_friends => 2) | |
227 | - | |
228 | - friend = create_user('friend').person | |
229 | - friend2 = create_user('friend2').person | |
230 | - friend3 = create_user('friend2').person | |
231 | - person.add_friend friend | |
232 | - person.add_friend friend2 | |
233 | - person.add_friend friend3 | |
234 | - | |
235 | - friend.add_friend suggested_person | |
236 | - | |
237 | - suggested_person.add_friend friend | |
238 | - suggested_person.add_friend friend2 | |
239 | - suggested_person.add_friend friend3 | |
240 | - | |
241 | - assert_difference 'ProfileSuggestion.find(suggestion.id).common_friends', 1 do | |
242 | - ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_friends(person), 'people_with_common_friends') | |
224 | +#FIXME This might not be necessary anymore... | |
225 | +# should 'update existing person suggestion when the number of common friends increase' do | |
226 | +# suggested_person = create_user('test_user').person | |
227 | +# suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_friends => 2) | |
228 | +# | |
229 | +# friend = create_user('friend').person | |
230 | +# friend2 = create_user('friend2').person | |
231 | +# friend3 = create_user('friend2').person | |
232 | +# person.add_friend friend | |
233 | +# person.add_friend friend2 | |
234 | +# person.add_friend friend3 | |
235 | +# | |
236 | +# friend.add_friend suggested_person | |
237 | +# | |
238 | +# suggested_person.add_friend friend | |
239 | +# suggested_person.add_friend friend2 | |
240 | +# suggested_person.add_friend friend3 | |
241 | +# | |
242 | +# assert_difference 'ProfileSuggestion.find(suggestion.id).common_friends', 1 do | |
243 | +# ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_friends(person), 'people_with_common_friends') | |
244 | +# end | |
245 | +# end | |
246 | +# | |
247 | +# should 'update existing person suggestion when the number of common communities increase' do | |
248 | +# suggested_person = create_user('test_user').person | |
249 | +# suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_communities => 1) | |
250 | +# | |
251 | +# community.add_member person | |
252 | +# community.add_member suggested_person | |
253 | +# | |
254 | +# community2 = fast_create(Community) | |
255 | +# community2.add_member person | |
256 | +# community2.add_member suggested_person | |
257 | +# | |
258 | +# assert_difference 'ProfileSuggestion.find(suggestion.id).common_communities', 1 do | |
259 | +# ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_communities(person), 'people_with_common_communities') | |
260 | +# end | |
261 | +# end | |
262 | +# | |
263 | +# should 'update existing person suggestion when the number of common tags increase' do | |
264 | +# suggested_person = create_user('test_user').person | |
265 | +# suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_tags => 1) | |
266 | +# | |
267 | +# create(Article, :created_by => person, :profile => person, :tag_list => 'first-tag, second-tag, third-tag, fourth-tag') | |
268 | +# create(Article, :created_by => suggested_person, :profile => suggested_person, :tag_list => 'first-tag, second-tag, third-tag') | |
269 | +# | |
270 | +# assert_difference 'ProfileSuggestion.find(suggestion.id).common_tags', 2 do | |
271 | +# ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_tags(person), 'people_with_common_tags') | |
272 | +# end | |
273 | +# end | |
274 | +# | |
275 | +# should 'update existing community suggestion when the number of common friends increase' do | |
276 | +# suggestion = ProfileSuggestion.create(:person => person, :suggestion => community, :common_friends => 1) | |
277 | +# | |
278 | +# member1 = create_user('member1').person | |
279 | +# member2 = create_user('member2').person | |
280 | +# | |
281 | +# person.add_friend member1 | |
282 | +# person.add_friend member2 | |
283 | +# | |
284 | +# community.add_member member1 | |
285 | +# community.add_member member2 | |
286 | +# | |
287 | +# assert_difference 'ProfileSuggestion.find(suggestion.id).common_friends', 1 do | |
288 | +# ProfileSuggestion.register_suggestions(person, ProfileSuggestion.communities_with_common_friends(person), 'communities_with_common_friends') | |
289 | +# end | |
290 | +# | |
291 | +# end | |
292 | +# | |
293 | +# should 'update existing community suggestion when the number of common tags increase' do | |
294 | +# other_person = create_user('test_user').person | |
295 | +# | |
296 | +# suggestion = ProfileSuggestion.create(:person => person, :suggestion => community, :common_tags => 1) | |
297 | +# | |
298 | +# create(Article, :created_by => person, :profile => person, :tag_list => 'first-tag, second-tag, third-tag, fourth-tag') | |
299 | +# create(Article, :created_by => other_person, :profile => community, :tag_list => 'first-tag, second-tag, third-tag') | |
300 | +# | |
301 | +# assert_difference 'ProfileSuggestion.find(suggestion.id).common_tags', 2 do | |
302 | +# ProfileSuggestion.register_suggestions(person, ProfileSuggestion.communities_with_common_tags(person), 'communities_with_common_tags') | |
303 | +# end | |
304 | +# end | |
305 | + | |
306 | + should 'register only new suggestions' do | |
307 | + person = create_user('person').person | |
308 | + ProfileSuggestion::SUGGESTIONS_BY_RULE.times do | |
309 | + ProfileSuggestion.create!(:person => person, :suggestion => fast_create(Person)) | |
243 | 310 | end |
244 | - end | |
245 | 311 | |
246 | - should 'update existing person suggestion when the number of common communities increase' do | |
247 | - suggested_person = create_user('test_user').person | |
248 | - suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_communities => 1) | |
312 | + person.reload | |
313 | + new_suggestion = fast_create(Person) | |
314 | + ids = (person.suggested_people + [new_suggestion]).map(&:id).join(',') | |
315 | + suggested_profiles = Profile.select('profiles.*, profiles.id as common_count').where("profiles.id IN (#{ids})") | |
249 | 316 | |
250 | - community.add_member person | |
251 | - community.add_member suggested_person | |
252 | - | |
253 | - community2 = fast_create(Community) | |
254 | - community2.add_member person | |
255 | - community2.add_member suggested_person | |
256 | - | |
257 | - assert_difference 'ProfileSuggestion.find(suggestion.id).common_communities', 1 do | |
258 | - ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_communities(person), 'people_with_common_communities') | |
317 | + assert_difference 'ProfileSuggestion.count', 1 do | |
318 | + ProfileSuggestion.register_suggestions(person, suggested_profiles, 'people_with_common_friends') | |
259 | 319 | end |
260 | 320 | end |
261 | 321 | |
262 | - should 'update existing person suggestion when the number of common tags increase' do | |
263 | - suggested_person = create_user('test_user').person | |
264 | - suggestion = ProfileSuggestion.create(:person => person, :suggestion => suggested_person, :common_tags => 1) | |
265 | - | |
266 | - create(Article, :created_by => person, :profile => person, :tag_list => 'first-tag, second-tag, third-tag, fourth-tag') | |
267 | - create(Article, :created_by => suggested_person, :profile => suggested_person, :tag_list => 'first-tag, second-tag, third-tag') | |
268 | - | |
269 | - assert_difference 'ProfileSuggestion.find(suggestion.id).common_tags', 2 do | |
270 | - ProfileSuggestion.register_suggestions(person, ProfileSuggestion.people_with_common_tags(person), 'people_with_common_tags') | |
322 | + should 'calculate new suggestions when number of available suggestions reaches the min_limit' do | |
323 | + person = create_user('person').person | |
324 | + (ProfileSuggestion::MIN_LIMIT + 1).times do | |
325 | + ProfileSuggestion.create!(:person => person, :suggestion => fast_create(Profile)) | |
271 | 326 | end |
272 | - end | |
273 | - | |
274 | - should 'update existing community suggestion when the number of common friends increase' do | |
275 | - suggestion = ProfileSuggestion.create(:person => person, :suggestion => community, :common_friends => 1) | |
276 | - | |
277 | - member1 = create_user('member1').person | |
278 | - member2 = create_user('member2').person | |
279 | 327 | |
280 | - person.add_friend member1 | |
281 | - person.add_friend member2 | |
328 | + ProfileSuggestion.expects(:calculate_suggestions) | |
282 | 329 | |
283 | - community.add_member member1 | |
284 | - community.add_member member2 | |
330 | + person.profile_suggestions.enabled.last.disable | |
331 | + person.profile_suggestions.enabled.last.destroy | |
332 | + process_delayed_job_queue | |
333 | + end | |
285 | 334 | |
286 | - assert_difference 'ProfileSuggestion.find(suggestion.id).common_friends', 1 do | |
287 | - ProfileSuggestion.register_suggestions(person, ProfileSuggestion.communities_with_common_friends(person), 'communities_with_common_friends') | |
335 | + should 'not create job to calculate new suggestions if there is already enough suggestions enabled' do | |
336 | + person = create_user('person').person | |
337 | + (ProfileSuggestion::MIN_LIMIT + 1).times do | |
338 | + ProfileSuggestion.create!(:person => person, :suggestion => fast_create(Profile)) | |
288 | 339 | end |
289 | 340 | |
341 | + ProfileSuggestion.expects(:calculate_suggestions).never | |
342 | + ProfileSuggestion.generate_profile_suggestions(person) | |
343 | + process_delayed_job_queue | |
290 | 344 | end |
291 | 345 | |
292 | - should 'update existing community suggestion when the number of common tags increase' do | |
293 | - other_person = create_user('test_user').person | |
294 | - | |
295 | - suggestion = ProfileSuggestion.create(:person => person, :suggestion => community, :common_tags => 1) | |
296 | - | |
297 | - create(Article, :created_by => person, :profile => person, :tag_list => 'first-tag, second-tag, third-tag, fourth-tag') | |
298 | - create(Article, :created_by => other_person, :profile => community, :tag_list => 'first-tag, second-tag, third-tag') | |
299 | - | |
300 | - assert_difference 'ProfileSuggestion.find(suggestion.id).common_tags', 2 do | |
301 | - ProfileSuggestion.register_suggestions(person, ProfileSuggestion.communities_with_common_tags(person), 'communities_with_common_tags') | |
346 | + should 'be able to force suggestions calculation' do | |
347 | + person = create_user('person').person | |
348 | + (ProfileSuggestion::MIN_LIMIT + 1).times do | |
349 | + ProfileSuggestion.create!(:person => person, :suggestion => fast_create(Profile)) | |
302 | 350 | end |
351 | + | |
352 | + ProfileSuggestion.expects(:calculate_suggestions) | |
353 | + ProfileSuggestion.generate_profile_suggestions(person, true) | |
354 | + process_delayed_job_queue | |
303 | 355 | end |
304 | 356 | end | ... | ... |