Skip to content

Commit

Permalink
Add pull_requests and done columns to task_list with migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
snewcomer authored and joshsmith committed Nov 6, 2017
1 parent ead9892 commit 994f7f3
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 12 deletions.
13 changes: 9 additions & 4 deletions lib/code_corps/model/task_list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ defmodule CodeCorps.TaskList do
@type t :: %__MODULE__{}

schema "task_lists" do
field :done, :boolean, default: false
field :inbox, :boolean, default: false
field :name, :string
field :order, :integer
field :position, :integer, virtual: true
field :pull_requests, :boolean, default: false

belongs_to :project, CodeCorps.Project
has_many :tasks, CodeCorps.Task
Expand All @@ -29,11 +31,11 @@ defmodule CodeCorps.TaskList do
name: "Backlog",
position: 2
}, %{
inbox: false,
pull_requests: true,
name: "In Progress",
position: 3
}, %{
inbox: false,
done: true,
name: "Done",
position: 4
}
Expand All @@ -52,8 +54,11 @@ defmodule CodeCorps.TaskList do

def create_changeset(struct, params) do
struct
|> cast(params, [:inbox])
|> cast(params, [:done, :inbox, :pull_requests])
|> changeset(params)
|> validate_required([:inbox])
|> validate_required([:done, :inbox, :pull_requests])
|> unique_constraint(:done, name: "task_lists_project_id_done_index")
|> unique_constraint(:inbox, name: "task_lists_project_id_inbox_index")
|> unique_constraint(:pull_requests, name: "task_lists_project_id_pull_requests_index")
end
end
2 changes: 1 addition & 1 deletion lib/code_corps_web/views/task_list_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule CodeCorpsWeb.TaskListView do
use CodeCorpsWeb, :view
use JaSerializer.PhoenixView

attributes [:inbox, :name, :order, :inserted_at, :updated_at]
attributes [:done, :inbox, :name, :order, :pull_requests, :inserted_at, :updated_at]

has_one :project, type: "project", field: :project_id

Expand Down
37 changes: 37 additions & 0 deletions priv/repo/migrations/20171106045740_add_done_to_task_list.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule CodeCorps.Repo.Migrations.AddDoneToTaskList do
use Ecto.Migration

import Ecto.Query

alias CodeCorps.Repo

def up do
alter table(:task_lists) do
add :done, :boolean, default: false
end

flush()

from(tl in "task_lists", where: [name: "Done"], update: [set: [done: true]])
|> Repo.update_all([])

task_list_query =
from(tl in "task_lists", where: [done: true], select: [:id])

# tests do not have any data, so we need to account for potential nil
case task_list_query |> Repo.one do
%{id: done_list_id} ->
task_update_query = from t in "tasks",
where: [status: "closed"],
update: [set: [task_list_id: ^done_list_id]]
task_update_query |> Repo.update_all([])
nil -> nil
end
end

def down do
alter table(:task_lists) do
remove :done
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
defmodule CodeCorps.Repo.Migrations.AddPullRequestsToTaskList do
use Ecto.Migration

import Ecto.Query

alias CodeCorps.Repo

def up do
alter table(:task_lists) do
add :pull_requests, :boolean, default: false
end

flush()

# set all "In Progress" task lists to now contain pull requests
from(
tl in "task_lists",
where: [name: "In Progress"],
update: [set: [pull_requests: true]]
) |> Repo.update_all([])

# get projects paired with associated pull request task list as ids
task_parent_data = from(
p in "projects",
left_join:
tl in "task_lists",
on: tl.project_id == p.id,
where: tl.pull_requests == true,
select: {p.id, tl.id}
) |> Repo.all

# get all tasks for projects, associated to github pull requests and
# assign them to the pull request task list
task_parent_data |> Enum.each(fn {project_id, pr_list_id} ->
from(
t in "tasks",
where: [project_id: ^project_id],
where: t.status != "closed",
where: not is_nil(t.github_issue_id),
inner_join:
gi in "github_issues",
on: t.github_issue_id == gi.id,
where: not is_nil(gi.github_pull_request_id),
update: [set: [task_list_id: ^pr_list_id]]
) |> Repo.update_all([])
end)
end

def down do
alter table(:task_lists) do
remove :pull_requests
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule CodeCorps.Repo.Migrations.AddUniqueConstraintsToSpecificTaskLists do
@moduledoc false

use Ecto.Migration

def change do
# There is already a "task_lists_project_id_index", so we name explicitly

create unique_index(
"task_lists", [:project_id],
where: "done = true", name: "task_lists_project_id_done_index")

create unique_index(
"task_lists", [:project_id],
where: "pull_requests = true", name: "task_lists_project_id_pull_requests_index")

create unique_index(
"task_lists", [:project_id],
where: "inbox = true", name: "task_lists_project_id_inbox_index")
end
end
27 changes: 25 additions & 2 deletions priv/repo/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,9 @@ CREATE TABLE task_lists (
project_id bigint,
inserted_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
inbox boolean DEFAULT false
inbox boolean DEFAULT false,
done boolean DEFAULT false,
pull_requests boolean DEFAULT false
);


Expand Down Expand Up @@ -3072,13 +3074,34 @@ CREATE INDEX task_lists_inbox_index ON task_lists USING btree (inbox);
CREATE INDEX task_lists_order_index ON task_lists USING btree ("order");


--
-- Name: task_lists_project_id_done_index; Type: INDEX; Schema: public; Owner: -
--

CREATE UNIQUE INDEX task_lists_project_id_done_index ON task_lists USING btree (project_id) WHERE (done = true);


--
-- Name: task_lists_project_id_inbox_index; Type: INDEX; Schema: public; Owner: -
--

CREATE UNIQUE INDEX task_lists_project_id_inbox_index ON task_lists USING btree (project_id) WHERE (inbox = true);


--
-- Name: task_lists_project_id_index; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX task_lists_project_id_index ON task_lists USING btree (project_id);


--
-- Name: task_lists_project_id_pull_requests_index; Type: INDEX; Schema: public; Owner: -
--

CREATE UNIQUE INDEX task_lists_project_id_pull_requests_index ON task_lists USING btree (project_id) WHERE (pull_requests = true);


--
-- Name: task_skills_skill_id_index; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3844,5 +3867,5 @@ ALTER TABLE ONLY users
-- PostgreSQL database dump complete
--

INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224), (20170224233516), (20170226050552), (20170228085250), (20170308214128), (20170308220713), (20170308222552), (20170313130611), (20170318032449), (20170318082740), (20170324194827), (20170424215355), (20170501225441), (20170505224222), (20170526095401), (20170602000208), (20170622205732), (20170626231059), (20170628092119), (20170628213609), (20170629183404), (20170630140136), (20170706132431), (20170707213648), (20170711122252), (20170717092127), (20170725060612), (20170727052644), (20170731130121), (20170814131722), (20170913114958), (20170921014405), (20170925214512), (20170925230419), (20170926134646), (20170927100300), (20170928234412), (20171003134956), (20171003225853), (20171006063358), (20171006161407), (20171012215106), (20171012221231), (20171016125229), (20171016125516), (20171016223356), (20171016235656), (20171017235433), (20171019191035), (20171025184225), (20171026010933), (20171027061833), (20171028011642), (20171028173508), (20171030182857), (20171031232023), (20171031234356), (20171101023309), (20171104013543);
INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224), (20170224233516), (20170226050552), (20170228085250), (20170308214128), (20170308220713), (20170308222552), (20170313130611), (20170318032449), (20170318082740), (20170324194827), (20170424215355), (20170501225441), (20170505224222), (20170526095401), (20170602000208), (20170622205732), (20170626231059), (20170628092119), (20170628213609), (20170629183404), (20170630140136), (20170706132431), (20170707213648), (20170711122252), (20170717092127), (20170725060612), (20170727052644), (20170731130121), (20170814131722), (20170913114958), (20170921014405), (20170925214512), (20170925230419), (20170926134646), (20170927100300), (20170928234412), (20171003134956), (20171003225853), (20171006063358), (20171006161407), (20171012215106), (20171012221231), (20171016125229), (20171016125516), (20171016223356), (20171016235656), (20171017235433), (20171019191035), (20171025184225), (20171026010933), (20171027061833), (20171028011642), (20171028173508), (20171030182857), (20171031232023), (20171031234356), (20171101023309), (20171104013543), (20171106045740), (20171106050209), (20171106103153);

121 changes: 116 additions & 5 deletions test/lib/code_corps/model/task_list_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule CodeCorps.TaskListTest do
use CodeCorps.ModelCase

alias CodeCorps.TaskList
alias Ecto.Changeset

@valid_attrs %{name: "some content", position: 42}
@invalid_attrs %{}
Expand All @@ -16,12 +17,122 @@ defmodule CodeCorps.TaskListTest do
refute changeset.valid?
end

test "is not inbox by default" do
test "defaults :done to 'false'" do
{:ok, record} =
%TaskList{}
|> TaskList.changeset(@valid_attrs)
|> CodeCorps.Repo.insert
%TaskList{} |> TaskList.changeset(@valid_attrs) |> Repo.insert
assert record.done == false
end

test "defaults :inbox to 'false'" do
{:ok, record} =
%TaskList{} |> TaskList.changeset(@valid_attrs) |> Repo.insert
assert record.inbox == false
end

test "defaults :pull_requests to 'false'" do
{:ok, record} =
%TaskList{} |> TaskList.changeset(@valid_attrs) |> Repo.insert
assert record.pull_requests == false
end

describe "create_changeset" do
test "casts done" do
attrs = @valid_attrs |> Map.merge(%{done: true})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
assert changeset |> Changeset.get_change(:done) == true
end

test "casts inbox" do
attrs = @valid_attrs |> Map.merge(%{inbox: true})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
assert changeset |> Changeset.get_change(:inbox) == true
end

test "casts pull_requests" do
attrs = @valid_attrs |> Map.merge(%{pull_requests: true})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
assert changeset |> Changeset.get_change(:pull_requests) == true
end

test "requires done" do
attrs = @valid_attrs |> Map.merge(%{done: nil})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:done)
end

test "requires inbox" do
attrs = @valid_attrs |> Map.merge(%{inbox: nil})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:inbox)
end

test "requires pull_requests" do
attrs = @valid_attrs |> Map.merge(%{pull_requests: nil})
changeset = %TaskList{} |> TaskList.create_changeset(attrs)
refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:pull_requests)
end

test "ensures a unique 'done' task list per project" do
%{id: project_id} = insert(:project)
attrs = @valid_attrs |> Map.merge(%{done: true})

{:ok, _task_list} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

{:error, changeset} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:done)
end

test "ensures a unique 'inbox' task list per project" do
%{id: project_id} = insert(:project)
attrs = @valid_attrs |> Map.merge(%{inbox: true})

{:ok, _task_list} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

{:error, changeset} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:inbox)
end

test "ensures a unique 'pull_requests' task list per project" do
%{id: project_id} = insert(:project)
attrs = @valid_attrs |> Map.merge(%{pull_requests: true})

{:ok, _task_list} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

{:error, changeset} =
%TaskList{}
|> TaskList.create_changeset(attrs)
|> Changeset.put_change(:project_id, project_id)
|> Repo.insert

refute record.inbox
refute changeset.valid?
assert changeset |> Map.get(:errors) |> Keyword.get(:pull_requests)
end
end
end
2 changes: 2 additions & 0 deletions test/lib/code_corps_web/views/task_list_view_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ defmodule CodeCorpsWeb.TaskListViewTest do
expected_json = %{
"data" => %{
"attributes" => %{
"done" => task_list.done,
"inbox" => task_list.inbox,
"name" => task_list.name,
"order" => 1000,
"pull-requests" => task_list.pull_requests,
"inserted-at" => task_list.inserted_at,
"updated-at" => task_list.updated_at,
},
Expand Down

0 comments on commit 994f7f3

Please sign in to comment.