profile_suggestion.rb
6.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
class ProfileSuggestion < ActiveRecord::Base
belongs_to :person
belongs_to :suggestion, :class_name => 'Profile', :foreign_key => :suggestion_id
attr_accessible :person, :suggestion, :suggestion_type, :categories, :enabled
before_create do |profile_suggestion|
profile_suggestion.suggestion_type = self.suggestion.class.to_s
end
acts_as_having_settings :field => :categories
validate :must_be_a_valid_category, :on => :create
def must_be_a_valid_category
if categories.keys.map { |cat| self.respond_to?(cat)}.include?(false)
errors.add(:categories, 'Category must be valid')
end
end
validates_uniqueness_of :suggestion_id, :scope => [ :person_id ]
scope :of_person, :conditions => { :suggestion_type => 'Person' }
scope :of_community, :conditions => { :suggestion_type => 'Community' }
scope :enabled, :conditions => { :enabled => true }
# {:category_type => ['category-icon', 'category-label']}
CATEGORIES = {
:common_friends => ['menu-people', _('Friends in common')],
:common_communities => ['menu-community',_('Communities in common')],
:common_tags => ['edit', _('Tags in common')]
}
CATEGORIES.keys.each do |category|
settings_items category.to_sym
attr_accessible category.to_sym
end
def category_icon(category)
'icon-' + ProfileSuggestion::CATEGORIES[category][0]
end
def category_label(category)
ProfileSuggestion::CATEGORIES[category][1]
end
RULES = %w[
friends_of_friends
people_with_common_communities
people_with_common_tags
communities_with_common_friends
communities_with_common_tags
]
# Number of suggestions
N_SUGGESTIONS = 30
# Number max of attempts
MAX_ATTEMPTS = N_SUGGESTIONS * 2
# Number of friends in common
COMMON_FRIENDS = 2
# Number of communities in common
COMMON_COMMUNITIES = 1
# Number of friends in common
COMMON_TAGS = 2
def self.friends_of_friends(person)
person_attempts = 0
person_friends = person.friends
person_friends.each do |friend|
friend.friends.includes.each do |friend_of_friend|
person_attempts += 1
return unless person.profile_suggestions.count < N_SUGGESTIONS && person_attempts < MAX_ATTEMPTS
unless friend_of_friend == person || friend_of_friend.is_a_friend?(person) || person.already_request_friendship?(friend_of_friend)
common_friends = friend_of_friend.friends & person_friends
if common_friends.size >= COMMON_FRIENDS
suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(friend_of_friend.id)
suggestion.common_friends = common_friends.size
suggestion.save
end
end
end
end
end
def self.people_with_common_communities(person)
person_attempts = 0
person_communities = person.communities
person_communities.each do |community|
community.members.each do |member|
person_attempts += 1
return unless person.profile_suggestions.count < N_SUGGESTIONS && person_attempts < MAX_ATTEMPTS
unless member == person || member.is_a_friend?(person) || person.already_request_friendship?(member)
common_communities = person_communities & member.communities
if common_communities.size >= COMMON_COMMUNITIES
suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(member.id)
suggestion.common_communities = common_communities.size
suggestion.save
end
end
end
end
end
def self.people_with_common_tags(person)
person_attempts = 0
tags = person.article_tags.keys
tags.each do |tag|
person_attempts += 1
return unless person.profile_suggestions.count < N_SUGGESTIONS && person_attempts < MAX_ATTEMPTS
tagged_content = ActsAsTaggableOn::Tagging.includes(:taggable).where(:tag_id => ActsAsTaggableOn::Tag.find_by_name(tag))
tagged_content.each do |tg|
author = tg.taggable.created_by
unless author.nil? || author == person || author.is_a_friend?(person) || person.already_request_friendship?(author)
common_tags = tags & author.article_tags.keys
if common_tags.size >= COMMON_TAGS
suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(author.id)
suggestion.common_tags = common_tags.size
suggestion.save
end
end
end
end
end
def self.communities_with_common_friends(person)
community_attempts = 0
person_friends = person.friends
person_friends.each do |friend|
friend.communities.each do |community|
community_attempts += 1
return unless person.profile_suggestions.count < N_SUGGESTIONS && community_attempts < MAX_ATTEMPTS
unless person.is_member_of?(community) || community.already_request_membership?(person)
common_friends = community.members & person.friends
if common_friends.size >= COMMON_FRIENDS
suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(community.id)
suggestion.common_friends = common_friends.size
suggestion.save
end
end
end
end
end
def self.communities_with_common_tags(person)
community_attempts = 0
tags = person.article_tags.keys
tags.each do |tag|
community_attempts += 1
return unless person.profile_suggestions.count < N_SUGGESTIONS && community_attempts < MAX_ATTEMPTS
tagged_content = ActsAsTaggableOn::Tagging.includes(:taggable).where(:tag_id => ActsAsTaggableOn::Tag.find_by_name(tag))
tagged_content.each do |tg|
profile = tg.taggable.profile
unless !profile.community? || person.is_member_of?(profile) || profile.already_request_membership?(person)
common_tags = tags & profile.article_tags.keys
if common_tags.size >= COMMON_TAGS
suggestion = person.profile_suggestions.find_or_initialize_by_suggestion_id(profile.id)
suggestion.common_tags = common_tags.size
suggestion.save
end
end
end
end
end
def disable
self.enabled = false
self.save
end
def self.generate_all_profile_suggestions
Delayed::Job.enqueue(ProfileSuggestion::GenerateAllJob.new) unless ProfileSuggestion::GenerateAllJob.exists?
end
def self.generate_profile_suggestions(person_id)
Delayed::Job.enqueue ProfileSuggestionsJob.new(person_id) unless ProfileSuggestionsJob.exists?(person_id)
end
class GenerateAllJob
def self.exists?
Delayed::Job.by_handler("--- !ruby/object:ProfileSuggestion::GenerateAllJob {}\n").count > 0
end
def perform
Person.find_each {|person| ProfileSuggestion.generate_profile_suggestions(person.id) }
end
end
end