diff --git a/lib/code_corps/user_task_matcher.ex b/lib/code_corps/user_task_matcher.ex new file mode 100644 index 000000000..38029cb3f --- /dev/null +++ b/lib/code_corps/user_task_matcher.ex @@ -0,0 +1,25 @@ +defmodule CodeCorps.UserTaskMatcher do + @moduledoc """ + Find the top tasks most matching a User's skills + """ + + alias CodeCorps.{Repo, Task, User, TaskSkill} + import Ecto.Query + + @spec match_user(User.t, number) :: [Task.t] + def match_user(%CodeCorps.User{} = user, tasks_count) do + query = from t in TaskSkill, + join: skill in assoc(t, :skill), + join: user_skill in assoc(skill, :user_skills), + join: user in assoc(user_skill, :user), + where: user.id == ^user.id, + group_by: t.task_id, + order_by: count(t.task_id), + limit: ^tasks_count, + select: t.task_id + + matches = query |> Repo.all + + Task |> where([t], t.id in ^matches) |> Repo.all + end +end diff --git a/test/lib/code_corps/user_task_matcher_test.exs b/test/lib/code_corps/user_task_matcher_test.exs new file mode 100644 index 000000000..353e4ccc5 --- /dev/null +++ b/test/lib/code_corps/user_task_matcher_test.exs @@ -0,0 +1,32 @@ +defmodule CodeCorps.UserTaskMatcherTest do + use CodeCorps.ModelCase + + import CodeCorps.UserTaskMatcher + + test "can find top x tasks for a user's skill" do + coding = insert(:skill, title: "coding") + design = insert(:skill, title: "design") + + account_page = insert(:task) + settings_page = insert(:task) + photoshop = insert(:task) + + insert(:task) + + insert(:task_skill, task: account_page, skill: design) + insert(:task_skill, task: account_page, skill: coding) + insert(:task_skill, task: settings_page, skill: design) + insert(:task_skill, task: settings_page, skill: coding) + insert(:task_skill, task: photoshop, skill: coding) + + user = insert(:user) + + insert(:user_skill, user: user, skill: design) + insert(:user_skill, user: user, skill: coding) + + tasks = match_user(user, 2) + + assert(length(tasks) == 2) + assert(length(match_user(user, 3)) == 3) + end +end diff --git a/web/models/skill.ex b/web/models/skill.ex index 4142c716c..b98479b2a 100644 --- a/web/models/skill.ex +++ b/web/models/skill.ex @@ -12,6 +12,7 @@ defmodule CodeCorps.Skill do has_many :roles, through: [:role_skills, :role] has_many :project_skills, CodeCorps.ProjectSkill + has_many :user_skills, CodeCorps.UserSkill has_many :projects, through: [:project_skills, :project] timestamps()