Add similarity score for users (#942)
This commit is contained in:
parent
7d783c2b9f
commit
305492c2c8
5 changed files with 132 additions and 39 deletions
|
|
@ -33,11 +33,7 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
handle_mentorship
|
||||
add_note
|
||||
@user.update!(user_params)
|
||||
if params[:quick_match]
|
||||
redirect_to "/internal/users/unmatched_mentee"
|
||||
else
|
||||
redirect_to "/internal/users/#{@user.id}"
|
||||
end
|
||||
redirect_to "/internal/users/unmatched_mentee"
|
||||
end
|
||||
|
||||
def handle_mentorship
|
||||
|
|
|
|||
63
app/labor/user_similarity.rb
Normal file
63
app/labor/user_similarity.rb
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
class UserSimilarity
|
||||
STOP_WORDS = %w(
|
||||
a cannot into our thus about co is ours to above
|
||||
could it ourselves together across down its out too
|
||||
after during itself over toward afterwards each last own
|
||||
towards again eg latter per under against either latterly
|
||||
perhaps until all else least rather up almost elsewhere
|
||||
less same upon alone enough ltd seem us along etc
|
||||
many seemed very already even may seeming via also ever
|
||||
me seems was although every meanwhile several we always
|
||||
everyone might she well among everything more should were
|
||||
amongst everywhere moreover since what an except most so
|
||||
whatever and few mostly some when another first much
|
||||
somehow whence any for must someone whenever anyhow
|
||||
former my something where anyone formerly myself sometime
|
||||
whereafter anything from namely sometimes whereas anywhere
|
||||
further neither somewhere whereby are had never still
|
||||
wherein around has nevertheless such whereupon as have
|
||||
next than wherever at he no that whether be hence
|
||||
nobody the whither became her none their which because
|
||||
here noone them while become hereafter nor themselves who
|
||||
becomes hereby not then whoever becoming herein nothing
|
||||
thence whole been hereupon now there whom before hers
|
||||
nowhere thereafter whose beforehand herself of thereby why
|
||||
behind him off therefore will being himself often therein
|
||||
with below his on thereupon within beside how once
|
||||
these without besides however one they would between i
|
||||
only this yet beyond ie onto those you both if or
|
||||
though your but in other through yours by inc others
|
||||
throughout yourself can indeed otherwise thru yourselves'
|
||||
).freeze
|
||||
|
||||
attr_accessor :first_user, :second_user
|
||||
def initialize(first_user, second_user)
|
||||
@first_user = first_user
|
||||
@second_user = second_user
|
||||
end
|
||||
|
||||
def score
|
||||
mentorship_score + profile_score + tag_score
|
||||
end
|
||||
|
||||
def mentorship_score
|
||||
(first_user.mentee_description.to_s.tr("0-9", "").split(" ") & second_user.mentor_description.to_s.tr("0-9", "").split(" ") - STOP_WORDS).size +
|
||||
(first_user.mentor_description.to_s.tr("0-9", "").split(" ") & second_user.mentee_description.to_s.tr("0-9", "").split(" ") - STOP_WORDS).size
|
||||
end
|
||||
|
||||
def profile_score
|
||||
summary_score = (first_user.summary.to_s.split(" ") & second_user.summary.to_s.split(" ") - STOP_WORDS).size
|
||||
mostly_work_with_score = (first_user.mostly_work_with.to_s.split(" ") & second_user.mostly_work_with.to_s.split(" ") - STOP_WORDS).size
|
||||
summary_score + mostly_work_with_score
|
||||
end
|
||||
|
||||
def tag_score
|
||||
tag_intersection.delete("discuss")
|
||||
tag_intersection.delete("hiring")
|
||||
tag_intersection.size * 2
|
||||
end
|
||||
|
||||
def tag_intersection
|
||||
first_user.cached_followed_tag_names & second_user.cached_followed_tag_names
|
||||
end
|
||||
end
|
||||
|
|
@ -108,41 +108,38 @@
|
|||
<% count = 0 %>
|
||||
<% MentorRelationship.
|
||||
unmatched_mentors.where.not(mentor_form_updated_at: nil, id: @user.id).
|
||||
order("mentor_form_updated_at DESC").each do |possible_mentor| %>
|
||||
<% break if count > 20 %>
|
||||
<% tag_intersection = ( @user.cached_followed_tag_names & possible_mentor.cached_followed_tag_names ) %>
|
||||
<% if tag_intersection.any? %>
|
||||
<% count = count + 1 %>
|
||||
<div class="row" style="font-size:0.9em">
|
||||
<div class="col-md-2">
|
||||
<img src="<%= possible_mentor.profile_image_90 %>" style="border-radius:100px;width:50px;height:50px;" />
|
||||
<br/>
|
||||
<a href="/<%= possible_mentor.username %>" target="_blank">@<%= possible_mentor.username %></a>
|
||||
<br/>
|
||||
<a href="/intertnal/users/<%= possible_mentor.id %>" target="_blank">Internal(<%= possible_mentor.id %>)</a>
|
||||
</div>
|
||||
<div class="col-md-3" style="border-left:1px solid black">
|
||||
<h4>Tag Intersection</h4>
|
||||
<%= tag_intersection.join(", ") %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Mentor description</h4>
|
||||
<%= possible_mentor.mentor_description %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Skills/Languages</h4>
|
||||
<%= possible_mentor.mostly_work_with %>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<h4>Action</h4>
|
||||
<%= form_for ([:internal, @user]) do |f| %>
|
||||
<%= f.hidden_field :quick_match, value: true %>
|
||||
<%= f.hidden_field :add_mentor, value: possible_mentor.id %>
|
||||
<%= f.submit "Match!" %>
|
||||
<% end %>
|
||||
</div>
|
||||
order("mentor_form_updated_at DESC").limit(175).
|
||||
sort_by { |possible_mentor| UserSimilarity.new(@user, possible_mentor).score }.reverse.
|
||||
first(20).each do |possible_mentor| %>
|
||||
<div class="row" style="font-size:0.9em">
|
||||
<div class="col-md-2">
|
||||
<img src="<%= possible_mentor.profile_image_90 %>" style="border-radius:100px;width:50px;height:50px;" />
|
||||
<br/>
|
||||
<a href="/<%= possible_mentor.username %>" target="_blank">@<%= possible_mentor.username %></a>
|
||||
<br/>
|
||||
<a href="/intertnal/users/<%= possible_mentor.id %>" target="_blank">Internal(<%= possible_mentor.id %>)</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col-md-3" style="border-left:1px solid black">
|
||||
<h4>Tag Intersection</h4>
|
||||
<%= UserSimilarity.new(@user, possible_mentor).tag_intersection.join(", ") %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Mentor description</h4>
|
||||
<%= possible_mentor.mentor_description %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Skills/Languages</h4>
|
||||
<%= possible_mentor.mostly_work_with %>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<h4>Action</h4>
|
||||
<%= form_for ([:internal, @user]) do |f| %>
|
||||
<%= f.hidden_field :quick_match, value: true %>
|
||||
<%= f.hidden_field :add_mentor, value: possible_mentor.id %>
|
||||
<%= f.submit "Match!" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
|
|
|||
29
spec/labor/user_similarity_spec.rb
Normal file
29
spec/labor/user_similarity_spec.rb
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe UserSimilarity, vcr: {} do
|
||||
let(:user) { create(:user, summary: "I like ruby and JavaScript and Go") }
|
||||
let(:similar_user) { create(:user, summary: "I like JavaScript and Go") }
|
||||
let(:dissimilar_user) { create(:user, summary: "I like Haskell and functional programming") }
|
||||
|
||||
it "It returns similar user" do
|
||||
simialar_score = UserSimilarity.new(user, similar_user).score
|
||||
dissimialar_score = UserSimilarity.new(user, dissimilar_user).score
|
||||
expect(simialar_score).to be > dissimialar_score
|
||||
end
|
||||
|
||||
it "Is not affected by stop words" do
|
||||
user.summary = user.summary + " throughout yourself can indeed otherwise thru yourselves through yours by inc others"
|
||||
dissimilar_user.summary = dissimilar_user.summary + " throughout yourself can indeed otherwise thru yourselves through yours by inc others"
|
||||
simialar_score = UserSimilarity.new(user, similar_user).score
|
||||
dissimialar_score = UserSimilarity.new(user, dissimilar_user).score
|
||||
expect(simialar_score).to be > dissimialar_score
|
||||
end
|
||||
|
||||
it "Is affected by non-stop words" do
|
||||
user.mentee_description = "Hot dogs languages punk rock hello"
|
||||
dissimilar_user.mentor_description = "Hot dogs languages punk rock hello "
|
||||
simialar_score = UserSimilarity.new(user, similar_user).score
|
||||
dissimialar_score = UserSimilarity.new(user, dissimilar_user).score
|
||||
expect(simialar_score).to be < dissimialar_score
|
||||
end
|
||||
end
|
||||
|
|
@ -119,6 +119,10 @@ RSpec.describe NotifyMailer, type: :mailer do
|
|||
mentee_email = described_class.mentee_email(mentee, mentor)
|
||||
expect(mentee_email.subject).to eq "You have been matched with a DEV mentor!"
|
||||
end
|
||||
it "renders proper from" do
|
||||
mentee_email = described_class.mentee_email(mentee, mentor)
|
||||
expect(mentee_email.from).to include "liana@dev.to"
|
||||
end
|
||||
end
|
||||
|
||||
describe "#mentor_email" do
|
||||
|
|
@ -128,6 +132,10 @@ RSpec.describe NotifyMailer, type: :mailer do
|
|||
mentor_email = described_class.mentor_email(mentor, mentee)
|
||||
expect(mentor_email.subject).to eq "You have been matched with a new DEV mentee!"
|
||||
end
|
||||
it "renders proper subject" do
|
||||
mentor_email = described_class.mentor_email(mentor, mentee)
|
||||
expect(mentor_email.from).to include "liana@dev.to"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue