Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/app/helpers/recommendations_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module RecommendationsHelper
MAX_RECOMMENDED_FUNCTIONS = 5

module RecommendationsPartialPath
def to_partial_path
'recommendations/function'
end
end

def more_from_user_function(function)
most_liked = user_most_function function.user, likes_count: :desc
most_commented = user_most_function function.user, comments_count: :desc
most_saved = user_most_function function.user, saves_count: :desc

recommended_functions = filter_unwanted [most_liked, most_commented, most_saved], function
override_partial_path recommended_functions, RecommendationsPartialPath
end

def similar_functions(function)
popularity_query = generate_popularity_query

popular_functions_from_tags = function.tags.map { |tag| tag.functions.order(popularity_query).first }
popular_functions = Function.order(Arel.sql(popularity_query))
.limit(MAX_RECOMMENDED_FUNCTIONS - popular_functions_from_tags.count)

recommended_functions = filter_unwanted [*popular_functions_from_tags, *popular_functions], function
override_partial_path recommended_functions, RecommendationsPartialPath
end

private

def override_partial_path(functions, partial_path_module)
functions.map { |obj| obj.extend(partial_path_module) }
end

def generate_popularity_query
likes_wieght = 1
comments_weight = 0.5
saves_weight = 0.25

"( (likes_count * #{likes_wieght}) + (comments_count * #{comments_weight}) + (saves_count * #{saves_weight}) ) desc"
end

# Returns the most x function for a certain user
# based on a criteria defined in `parameter`.
#
# @param user [User]
# @param parameter [Hash]
# @returns [Function]
def user_most_function(user, parameter)
user.functions.order(parameter).first
end

# Filters an array of Functions. It removes an `unwated_function`
# and any `nil` variables in the `functions` array.
#
# @param functions [Array<Function>]
#
# @param unwanted_functon [Function] a function to be filtered
# out of the Functions array.
#
# @returns [Array<Function>]
def filter_unwanted(functions, unwanted_function)
functions.reject { |func| func.nil? || func == unwanted_function }.uniq
end
end
16 changes: 12 additions & 4 deletions src/app/views/functions/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<%= content_for :title, sprintf("%s - by: %s", @function.name, @user.name) %>
<%= render 'tags/tags', tags: @function.tags %>
<%= render @function, full: true %>
<%= render @function.comments %>
<%= render 'comments/form', comment: @comment if can?(@comment, :create) %>

<div class="columns">
<div class="column is-four-fifths">
<%= render 'tags/tags', tags: @function.tags %>
<%= render @function, full: true %>
<%= render @function.comments %>
<%= render 'comments/form', comment: @comment if can?(@comment, :create) %>
</div>
<div class="column">
<%= render 'recommendations/recommendations', function: @function %>
</div>
</div>
1 change: 1 addition & 0 deletions src/app/views/recommendations/_function.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= link_to "#{function.user.username}/#{function.name}", [function.user, function], class: 'panel-block' %>
10 changes: 10 additions & 0 deletions src/app/views/recommendations/_recommendation.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<% unless functions.empty? %>

<article class="panel has-background-white">
<p class="panel-heading">
<%= recommendation_title %>
</p>
<%= render functions %>
</article>

<% end %>
2 changes: 2 additions & 0 deletions src/app/views/recommendations/_recommendations.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<%= render 'recommendations/recommendation', recommendation_title: 'Similar Functions', functions: similar_functions(function) %>
<%= render 'recommendations/recommendation', recommendation_title: "More from #{function.user.name}", functions: more_from_user_function(function) %>
14 changes: 14 additions & 0 deletions src/spec/helpers/recommendations_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'rails_helper'

RSpec.describe RecommendationsHelper do
let!(:users) { create_list(:user, 5) }
let(:functions) { users.map { |user| create_list(:function, 5, user: user) }.flatten }

describe '#more_from_user_function' do
it { expect(helper.more_from_user_function(functions.sample)).to include(a_kind_of(Function)) }
end

describe '#similar_functions' do
it { expect(helper.similar_functions(functions.sample)).to include(a_kind_of(Function)) }
end
end