Skip to content

Commit d9f8dd0

Browse files
committed
Add TaskSkill table, model and tests
1 parent 60c06de commit d9f8dd0

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule CodeCorps.Repo.Migrations.CreateTaskSkill do
2+
@moduledoc false
3+
4+
use Ecto.Migration
5+
6+
def change do
7+
create table(:task_skills) do
8+
add :skill_id, references(:skills), null: false
9+
add :task_id, references(:tasks), null: false
10+
11+
timestamps()
12+
end
13+
14+
create index :task_skills, [:task_id, :skill_id], unique: true
15+
end
16+
end

test/models/task_skill_test.exs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
defmodule CodeCorps.TaskSkillTest do
2+
@moduledoc false
3+
4+
use CodeCorps.ModelCase
5+
6+
alias CodeCorps.TaskSkill
7+
8+
describe "create_changeset/2" do
9+
@required_attrs ~w(task_id skill_id)
10+
11+
test "requires #{@required_attrs}" do
12+
changeset = TaskSkill.create_changeset(%TaskSkill{}, %{})
13+
14+
assert_validation_triggered(changeset, :task_id, :required)
15+
assert_validation_triggered(changeset, :skill_id, :required)
16+
end
17+
18+
test "ensures associated Task record exists" do
19+
skill = insert(:skill)
20+
changeset = TaskSkill.create_changeset(%TaskSkill{}, %{task_id: -1, skill_id: skill.id})
21+
22+
{:error, response_changeset} = Repo.insert(changeset)
23+
assert_error_message(response_changeset, :task, "does not exist")
24+
end
25+
26+
test "ensures associated Skill record exists" do
27+
task = insert(:task)
28+
changeset = TaskSkill.create_changeset(%TaskSkill{}, %{task_id: task.id, skill_id: -1})
29+
30+
{:error, response_changeset} = Repo.insert(changeset)
31+
assert_error_message(response_changeset, :skill, "does not exist")
32+
end
33+
34+
test "ensures uniqueness of Skill/Task combination" do
35+
task_skill = insert(:task_skill)
36+
37+
changeset = TaskSkill.create_changeset(%TaskSkill{}, %{task_id: task_skill.task_id, skill_id: task_skill.skill_id})
38+
39+
{:error, response_changeset} = Repo.insert(changeset)
40+
assert_error_message(response_changeset, :skill, "has already been taken")
41+
end
42+
end
43+
end

test/support/factories.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
defmodule CodeCorps.Factories do
2+
@moduledoc false
3+
24
# with Ecto
35
use ExMachina.Ecto, repo: CodeCorps.Repo
46

@@ -64,6 +66,13 @@ defmodule CodeCorps.Factories do
6466
}
6567
end
6668

69+
def task_skill_factory do
70+
%CodeCorps.TaskSkill{
71+
skill: build(:skill),
72+
task: build(:task)
73+
}
74+
end
75+
6776
def project_factory do
6877
%CodeCorps.Project{
6978
title: sequence(:title, &"Project #{&1}"),
@@ -94,6 +103,7 @@ defmodule CodeCorps.Factories do
94103
}
95104
end
96105

106+
@spec set_password(CodeCorps.User.t, String.t) :: CodeCorps.User.t
97107
def set_password(user, password) do
98108
hashed_password = Comeonin.Bcrypt.hashpwsalt(password)
99109
%{user | encrypted_password: hashed_password}

web/models/task_skill.ex

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
defmodule CodeCorps.TaskSkill do
2+
@moduledoc """
3+
Represents a link record between a task and a skill, indicating that
4+
for a user to be suitable to work on a task, they need to posses skills
5+
associated with that task.
6+
"""
7+
use CodeCorps.Web, :model
8+
9+
@type t :: %__MODULE__{}
10+
11+
schema "task_skills" do
12+
belongs_to :skill, CodeCorps.Skill
13+
belongs_to :task, CodeCorps.Task
14+
15+
timestamps()
16+
end
17+
18+
@permitted_attrs [:skill_id, :task_id]
19+
@required_attrs @permitted_attrs
20+
21+
@doc """
22+
Builds a changeset used to insert a record into the database
23+
"""
24+
@spec create_changeset(CodeCorps.TaskSkill.t, map) :: Ecto.Changeset.t
25+
def create_changeset(struct, params \\ %{}) do
26+
struct
27+
|> cast(params, @permitted_attrs)
28+
|> validate_required(@required_attrs)
29+
|> assoc_constraint(:task)
30+
|> assoc_constraint(:skill)
31+
|> unique_constraint(:skill, name: :task_skills_task_id_skill_id_index)
32+
end
33+
end

0 commit comments

Comments
 (0)