Skip to content

Commit 3edfb9c

Browse files
committed
implemented similar functions
1 parent f146adf commit 3edfb9c

File tree

5 files changed

+86
-20
lines changed

5 files changed

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