Skip to content

Commit 5bac43f

Browse files
committed
implemented similar functions
1 parent f146adf commit 5bac43f

File tree

5 files changed

+85
-20
lines changed

5 files changed

+85
-20
lines changed
Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,65 @@
11
module RecommendationsHelper
2-
MAX_USER_RECCOMMENDED_FUNCTIONS = 5
2+
MAX_RECOMMENDED_FUNCTIONS = 5
33

44
module RecommendationsPartialPath
55
def to_partial_path
66
'recommendations/function'
77
end
88
end
99

10-
def more_from_user(user)
11-
most_liked = user.functions.order(likes_count: :desc).first
12-
most_commented = user.functions.order(comments_count: :desc).first
13-
most_saved = user.functions.order(saves_count: :desc).first
10+
def more_from_user_function(function)
11+
most_liked = user_most_function function.user, likes_count: :desc
12+
most_commented = user_most_function function.user, comments_count: :desc
13+
most_saved = user_most_function function.user, saves_count: :desc
1414

15-
[most_liked, most_saved, most_commented].uniq.map { |obj| obj.extend(RecommendationsPartialPath) }
15+
override_partial_path filter_unwanted([most_liked, most_commented, most_saved], function), RecommendationsPartialPath
16+
end
17+
18+
def similar_functions(function)
19+
popularity_query = generate_popularity_query
20+
21+
popular_functions_from_tags = function.tags.map { |tag| tag.functions.order(popularity_query).first }
22+
popular_functions = Function.order(Arel.sql(popularity_query))
23+
.limit(MAX_RECOMMENDED_FUNCTIONS - popular_functions_from_tags.count)
24+
25+
similar_functions = [*popular_functions_from_tags, *popular_functions]
26+
override_partial_path filter_unwanted(similar_functions, function), RecommendationsPartialPath
27+
end
28+
29+
private
30+
31+
def override_partial_path(functions, partial_path_module)
32+
functions.map { |obj| obj.extend(partial_path_module) }
33+
end
34+
35+
def generate_popularity_query
36+
likes_wieght = 1
37+
comments_weight = 0.5
38+
saves_weight = 0.25
39+
40+
"( (likes_count * #{likes_wieght}) + (comments_count * #{comments_weight}) + (saves_count * #{saves_weight}) ) desc"
41+
end
42+
43+
# Returns the most x function for a certain user
44+
# based on a criteria defined in `parameter`.
45+
#
46+
# @param user [User]
47+
# @param parameter [Hash]
48+
# @returns [Function]
49+
def user_most_function(user, parameter)
50+
user.functions.order(parameter).first
51+
end
52+
53+
# Filters an array of Functions. It removes an `unwated_function`
54+
# and any `nil` variables in the `functions` array.
55+
#
56+
# @param functions [Array<Function>]
57+
#
58+
# @param unwanted_functon [Function] a function to be filtered
59+
# out of the Functions array.
60+
#
61+
# @returns [Array<Function>]
62+
def filter_unwanted(functions, unwanted_function)
63+
functions.reject { |func| func.nil? || func == unwanted_function }.uniq
1664
end
1765
end
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
<%= content_for :title, sprintf("%s - by: %s", @function.name, @user.name) %>
22

33
<div class="columns">
4-
<div class="column">
5-
<%= render 'recommendations/recommendations', function: @function %>
6-
</div>
74
<div class="column is-four-fifths">
85
<%= render 'tags/tags', tags: @function.tags %>
96
<%= render @function, full: true %>
7+
<%= render @function.comments %>
8+
<%= render 'comments/form', comment: @comment if can?(@comment, :create) %>
9+
</div>
10+
<div class="column">
11+
<%= render 'recommendations/recommendations', function: @function %>
1012
</div>
1113
</div>
12-
13-
<%= render @function.comments %>
14-
<%= render 'comments/form', comment: @comment if can?(@comment, :create) %>
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
<article class="panel has-background-white">
2-
<p class="panel-heading">
3-
<%= recommendation_title %>
4-
</p>
5-
<%= render functions %>
6-
</article>
1+
<% unless functions.empty? %>
2+
3+
<article class="panel has-background-white">
4+
<p class="panel-heading">
5+
<%= recommendation_title %>
6+
</p>
7+
<%= render functions %>
8+
</article>
9+
10+
<% end %>
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
<%= render 'recommendations/recommendation', recommendation_title: 'Similar Functions', functions: more_from_user(function.user) %>
2-
<%= render 'recommendations/recommendation', recommendation_title: "More from #{function.user.name}", functions: more_from_user(function.user) %>
1+
<%= render 'recommendations/recommendation', recommendation_title: 'Similar Functions', functions: similar_functions(function) %>
2+
<%= render 'recommendations/recommendation', recommendation_title: "More from #{function.user.name}", functions: more_from_user_function(function) %>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe RecommendationsHelper do
4+
let!(:users) { create_list(:user, 5) }
5+
let(:functions) { users.map { |user| create_list(:function, 5, user: user) }.flatten }
6+
7+
describe '#more_from_user_function' do
8+
it { expect(helper.more_from_user_function(functions.sample)).to include(a_kind_of(Function)) }
9+
end
10+
11+
describe '#similar_functions' do
12+
it { expect(helper.similar_functions(functions.sample)).to include(a_kind_of(Function)) }
13+
end
14+
end

0 commit comments

Comments
 (0)