From 71cbf60b135eb2c68227bec0cb9152b57f1426e7 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Mon, 15 Nov 2021 06:37:13 +0700 Subject: [PATCH 01/23] chore: add ds_store to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f62cb51..b815609 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ diskuy-*.tar # this depending on your deployment strategy. /priv/static/ +.DS_Store -- GitLab From 93db186dbae8c0aca6014b67a024bcc993bffdee Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Mon, 15 Nov 2021 06:46:07 +0700 Subject: [PATCH 02/23] build: add my own local db setup --- config/dev.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/dev.exs b/config/dev.exs index b56ce17..30476c0 100755 --- a/config/dev.exs +++ b/config/dev.exs @@ -2,9 +2,9 @@ use Mix.Config # Configure your database config :diskuy, Diskuy.Repo, - username: "rafif", - password: "rafif123", - database: "diskuy_dev_new", + username: "diskuy", + password: "diskuy", + database: "diskuy_dev", hostname: "localhost", show_sensitive_data_on_connection_error: true, pool_size: 10 -- GitLab From be9f29f9386063bb568c6cb60a0567aff3e323b7 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Thu, 25 Nov 2021 23:41:37 +0700 Subject: [PATCH 03/23] feat(model): add Vote, Poll, and Choice models --- lib/diskuy/survey/choice.ex | 18 ++++++++++++++++++ lib/diskuy/survey/poll.ex | 32 ++++++++++++++++++++++++++++++++ lib/diskuy/survey/vote.ex | 18 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 lib/diskuy/survey/choice.ex create mode 100644 lib/diskuy/survey/poll.ex create mode 100644 lib/diskuy/survey/vote.ex diff --git a/lib/diskuy/survey/choice.ex b/lib/diskuy/survey/choice.ex new file mode 100644 index 0000000..3366c98 --- /dev/null +++ b/lib/diskuy/survey/choice.ex @@ -0,0 +1,18 @@ +defmodule Diskuy.Survey.Choice do + use Ecto.Schema + import Ecto.Changeset + + schema "choice" do + field :name, :string + belongs_to :poll, Survey.Poll + has_many :vote, Survey.Vote + + timestamps() + end + + @doc false + def changeset(post, attrs) do + post + |> cast(attrs, [:name, :points, :poll]) + end +end diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex new file mode 100644 index 0000000..1be8661 --- /dev/null +++ b/lib/diskuy/survey/poll.ex @@ -0,0 +1,32 @@ +defmodule Diskuy.Survey.Poll do + use Ecto.Schema + import Ecto.Changeset + alias Diskuy.Utility.Utility + + schema "poll" do + field :points, :integer + field :title, :string + field :topic_id, :id + field :user_id, :id + has_many :choice, Survey.Choice + + timestamps() + end + + @doc false + def changeset(thread, attrs) do + thread + |> cast(attrs, [:title, :points, :topic_id, :user_id, :choice]) + |> capitalize_title + end + + defp capitalize_title(changeset) do + case changeset do + %Ecto.Changeset{valid?: true, changes: %{title: title}} + -> + put_change(changeset, :title, Utility.capitalize_string(title)) + _ -> + changeset + end + end +end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex new file mode 100644 index 0000000..b5b5c9f --- /dev/null +++ b/lib/diskuy/survey/vote.ex @@ -0,0 +1,18 @@ +defmodule Diskuy.Survey.Vote do + use Ecto.Schema + import Ecto.Changeset + + schema "choice" do + field :user_id, :id + field :poll_id, :id + field :choice_id, :id + + timestamps() + end + + @doc false + def changeset(post, attrs) do + post + |> cast(attrs, [:user_id, :points, :poll]) + end +end -- GitLab From 10434f57648dcb822273abe06b997a2c4e354d9a Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sun, 28 Nov 2021 06:32:20 +0700 Subject: [PATCH 04/23] feat(model): modify some attrs --- lib/diskuy/survey.ex | 219 ++++++++++++++++++++++++++++++++++++ lib/diskuy/survey/choice.ex | 2 +- lib/diskuy/survey/poll.ex | 2 +- lib/diskuy/survey/vote.ex | 2 +- 4 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 lib/diskuy/survey.ex diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex new file mode 100644 index 0000000..c6ebb90 --- /dev/null +++ b/lib/diskuy/survey.ex @@ -0,0 +1,219 @@ +defmodule Diskuy.Forum do + @moduledoc """ + The Survey context. + """ + + import Ecto.Query, warn: false + alias Diskuy.Repo + + alias Diskuy.Forum.Topic + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking topic changes. + + ## Examples + + iex> change_topic(topic) + %Ecto.Changeset{data: %Topic{}} + + """ + def change_topic(%Topic{} = topic, attrs \\ %{}) do + Topic.changeset(topic, attrs) + end + + alias Diskuy.Survey.Poll + + @doc """ + Returns the list of threads. + + ## Examples + + iex> list_polls() + [%Thread{}, ...] + + """ + def list_polls do + query = from p in Poll, order_by: p.inserted_at + Repo.all(query) + end + + @doc """ + Gets a single poll. + + Raises `Ecto.NoResultsError` if the Poll does not exist. + + ## Examples + + iex> get_poll!(123) + %Thread{} + + iex> get_poll!(456) + ** (Ecto.NoResultsError) + + """ + def get_poll!(id), do: Repo.get!(Poll, id) + + @doc """ + Creates a poll. + + ## Examples + + iex> create_poll(%{field: value}) + {:ok, %Poll{}} + + iex> create_poll(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_poll(attrs \\ %{}) do + %Poll{} + |> Poll.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a poll. + + ## Examples + + iex> update_poll(poll, %{field: new_value}) + {:ok, %Poll{}} + + iex> update_poll(poll, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_poll(%Poll{} = poll, attrs) do + poll + |> Poll.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a poll. + + ## Examples + + iex> delete_poll(poll) + {:ok, %Thread{}} + + iex> delete_poll(poll) + {:error, %Ecto.Changeset{}} + + """ + def delete_poll(%Poll{} = poll) do + Repo.delete(poll) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking poll changes. + + ## Examples + + iex> change_poll(poll) + %Ecto.Changeset{data: %Poll{}} + + """ + def change_poll(%Poll{} = poll, attrs \\ %{}) do + Poll.changeset(poll, attrs) + end + + alias Diskuy.Survey.Choice + + @doc """ + Returns the list of surveys. + + ## Examples + + iex> list_surveys() + [%Post{}, ...] + + """ + def list_surveys do + query = from p in Post, order_by: p.inserted_at + Repo.all(query) + end + + alias Diskuy.Forum.Post + + @doc """ + Gets a single survey. + + Raises `Ecto.NoResultsError` if the Post does not exist. + + ## Examples + + iex> get_survey!(123) + %Post{} + + iex> get_survey!(456) + ** (Ecto.NoResultsError) + + """ + def get_survey!(id), do: Repo.get!(Post, id) + + @doc """ + Creates a survey. + + ## Examples + + iex> create_survey(%{field: value}) + {:ok, %Post{}} + + iex> create_survey(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_survey(attrs \\ %{}) do + %Post{} + |> Post.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a survey. + + ## Examples + + iex> update_survey(survey, %{field: new_value}) + {:ok, %Post{}} + + iex> update_survey(survey, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_survey(%Post{} = survey, attrs) do + survey + |> Post.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a survey. + + ## Examples + + iex> delete_survey(survey) + {:ok, %Post{}} + + iex> delete_survey(survey) + {:error, %Ecto.Changeset{}} + + """ + def delete_survey(%Post{} = survey) do + Repo.delete(survey) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking survey changes. + + ## Examples + + iex> change_survey(survey) + %Ecto.Changeset{data: %Post{}} + + """ + def change_survey(%Post{} = survey, attrs \\ %{}) do + Post.changeset(survey, attrs) + end +end diff --git a/lib/diskuy/survey/choice.ex b/lib/diskuy/survey/choice.ex index 3366c98..7749397 100644 --- a/lib/diskuy/survey/choice.ex +++ b/lib/diskuy/survey/choice.ex @@ -2,7 +2,7 @@ defmodule Diskuy.Survey.Choice do use Ecto.Schema import Ecto.Changeset - schema "choice" do + schema "choices" do field :name, :string belongs_to :poll, Survey.Poll has_many :vote, Survey.Vote diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex index 1be8661..155b015 100644 --- a/lib/diskuy/survey/poll.ex +++ b/lib/diskuy/survey/poll.ex @@ -3,7 +3,7 @@ defmodule Diskuy.Survey.Poll do import Ecto.Changeset alias Diskuy.Utility.Utility - schema "poll" do + schema "polls" do field :points, :integer field :title, :string field :topic_id, :id diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index b5b5c9f..fd13537 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -2,7 +2,7 @@ defmodule Diskuy.Survey.Vote do use Ecto.Schema import Ecto.Changeset - schema "choice" do + schema "votes" do field :user_id, :id field :poll_id, :id field :choice_id, :id -- GitLab From 11b12b4148167081da339f222abb5ce2cbd3695d Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sun, 28 Nov 2021 14:22:52 +0700 Subject: [PATCH 05/23] feat(model): add datetime attr --- lib/diskuy/survey.ex | 2 +- lib/diskuy/survey/poll.ex | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index c6ebb90..ab3284e 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -1,4 +1,4 @@ -defmodule Diskuy.Forum do +defmodule Diskuy.Survey do @moduledoc """ The Survey context. """ diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex index 155b015..754de02 100644 --- a/lib/diskuy/survey/poll.ex +++ b/lib/diskuy/survey/poll.ex @@ -8,6 +8,7 @@ defmodule Diskuy.Survey.Poll do field :title, :string field :topic_id, :id field :user_id, :id + field :end_time, :utc_datetime has_many :choice, Survey.Choice timestamps() -- GitLab From b4c48fad40dc306fad4860044f5ec5cc5d3201b8 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 14:08:54 +0700 Subject: [PATCH 06/23] feat(schema): add phx.gen.context generated Poll and Choice schema --- lib/diskuy/survey.ex | 103 ++++++------- lib/diskuy/survey/choice.ex | 10 +- lib/diskuy/survey/poll.ex | 23 +-- .../20211211063946_create_polls.exs | 18 +++ .../20211211064623_create_choices.exs | 14 ++ .../20211211065116_create_polls.exs | 19 +++ .../20211211065254_create_choices.exs | 14 ++ test/diskuy/survey_test.exs | 139 ++++++++++++++++++ 8 files changed, 258 insertions(+), 82 deletions(-) create mode 100644 priv/repo/migrations/20211211063946_create_polls.exs create mode 100644 priv/repo/migrations/20211211064623_create_choices.exs create mode 100644 priv/repo/migrations/20211211065116_create_polls.exs create mode 100644 priv/repo/migrations/20211211065254_create_choices.exs create mode 100644 test/diskuy/survey_test.exs diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index ab3284e..8741fd4 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -6,35 +6,19 @@ defmodule Diskuy.Survey do import Ecto.Query, warn: false alias Diskuy.Repo - alias Diskuy.Forum.Topic - - @doc """ - Returns an `%Ecto.Changeset{}` for tracking topic changes. - - ## Examples - - iex> change_topic(topic) - %Ecto.Changeset{data: %Topic{}} - - """ - def change_topic(%Topic{} = topic, attrs \\ %{}) do - Topic.changeset(topic, attrs) - end - alias Diskuy.Survey.Poll @doc """ - Returns the list of threads. + Returns the list of polls. ## Examples iex> list_polls() - [%Thread{}, ...] + [%Poll{}, ...] """ def list_polls do - query = from p in Poll, order_by: p.inserted_at - Repo.all(query) + Repo.all(Poll) end @doc """ @@ -45,7 +29,7 @@ defmodule Diskuy.Survey do ## Examples iex> get_poll!(123) - %Thread{} + %Poll{} iex> get_poll!(456) ** (Ecto.NoResultsError) @@ -95,7 +79,7 @@ defmodule Diskuy.Survey do ## Examples iex> delete_poll(poll) - {:ok, %Thread{}} + {:ok, %Poll{}} iex> delete_poll(poll) {:error, %Ecto.Changeset{}} @@ -121,99 +105,98 @@ defmodule Diskuy.Survey do alias Diskuy.Survey.Choice @doc """ - Returns the list of surveys. + Returns the list of choices. ## Examples - iex> list_surveys() - [%Post{}, ...] + iex> list_choices() + [%Choice{}, ...] """ - def list_surveys do - query = from p in Post, order_by: p.inserted_at - Repo.all(query) + def list_choices(poll) do + from(c in Choice, where: [poll_id: ^poll.id], order_by: [asc: :id]) + |> Repo.all() end - alias Diskuy.Forum.Post - @doc """ - Gets a single survey. + Gets a single choice. - Raises `Ecto.NoResultsError` if the Post does not exist. + Raises `Ecto.NoResultsError` if the Choice does not exist. ## Examples - iex> get_survey!(123) - %Post{} + iex> get_choice!(123) + %Choice{} - iex> get_survey!(456) + iex> get_choice!(456) ** (Ecto.NoResultsError) """ - def get_survey!(id), do: Repo.get!(Post, id) + def get_choice!(poll, id), do: Repo.get_by!(Choice, poll_id: poll.id, id: id) @doc """ - Creates a survey. + Creates a choice. ## Examples - iex> create_survey(%{field: value}) - {:ok, %Post{}} + iex> create_choice(%{field: value}) + {:ok, %Choice{}} - iex> create_survey(%{field: bad_value}) + iex> create_choice(%{field: bad_value}) {:error, %Ecto.Changeset{}} """ - def create_survey(attrs \\ %{}) do - %Post{} - |> Post.changeset(attrs) + def create_choice(attrs \\ %{}) do + %Choice{} + |> Ecto.build_assoc(:choices) + |> Choice.changeset(attrs) |> Repo.insert() end @doc """ - Updates a survey. + Updates a choice. ## Examples - iex> update_survey(survey, %{field: new_value}) - {:ok, %Post{}} + iex> update_choice(choice, %{field: new_value}) + {:ok, %Choice{}} - iex> update_survey(survey, %{field: bad_value}) + iex> update_choice(choice, %{field: bad_value}) {:error, %Ecto.Changeset{}} """ - def update_survey(%Post{} = survey, attrs) do - survey - |> Post.changeset(attrs) + def update_choice(%Choice{} = choice, attrs) do + choice + |> Choice.changeset(attrs) |> Repo.update() end @doc """ - Deletes a survey. + Deletes a choice. ## Examples - iex> delete_survey(survey) - {:ok, %Post{}} + iex> delete_choice(choice) + {:ok, %Choice{}} - iex> delete_survey(survey) + iex> delete_choice(choice) {:error, %Ecto.Changeset{}} """ - def delete_survey(%Post{} = survey) do - Repo.delete(survey) + def delete_choice(%Choice{} = choice) do + Repo.delete(choice) end @doc """ - Returns an `%Ecto.Changeset{}` for tracking survey changes. + Returns an `%Ecto.Changeset{}` for tracking choice changes. ## Examples - iex> change_survey(survey) - %Ecto.Changeset{data: %Post{}} + iex> change_choice(choice) + %Ecto.Changeset{data: %Choice{}} """ - def change_survey(%Post{} = survey, attrs \\ %{}) do - Post.changeset(survey, attrs) + def change_choice(%Choice{} = choice, attrs \\ %{}) do + Choice.changeset(choice, attrs) end end diff --git a/lib/diskuy/survey/choice.ex b/lib/diskuy/survey/choice.ex index 7749397..fc159ca 100644 --- a/lib/diskuy/survey/choice.ex +++ b/lib/diskuy/survey/choice.ex @@ -4,15 +4,15 @@ defmodule Diskuy.Survey.Choice do schema "choices" do field :name, :string - belongs_to :poll, Survey.Poll - has_many :vote, Survey.Vote + belongs_to :poll, Diskuy.Survey.Poll timestamps() end @doc false - def changeset(post, attrs) do - post - |> cast(attrs, [:name, :points, :poll]) + def changeset(choice, attrs) do + choice + |> cast(attrs, [:name]) + |> validate_required([:name]) end end diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex index 754de02..12b1955 100644 --- a/lib/diskuy/survey/poll.ex +++ b/lib/diskuy/survey/poll.ex @@ -1,33 +1,22 @@ defmodule Diskuy.Survey.Poll do use Ecto.Schema import Ecto.Changeset - alias Diskuy.Utility.Utility schema "polls" do + field :end_time, :utc_datetime field :points, :integer field :title, :string field :topic_id, :id field :user_id, :id - field :end_time, :utc_datetime - has_many :choice, Survey.Choice + has_many :choices, Diskuy.Survey.Choice timestamps() end @doc false - def changeset(thread, attrs) do - thread - |> cast(attrs, [:title, :points, :topic_id, :user_id, :choice]) - |> capitalize_title - end - - defp capitalize_title(changeset) do - case changeset do - %Ecto.Changeset{valid?: true, changes: %{title: title}} - -> - put_change(changeset, :title, Utility.capitalize_string(title)) - _ -> - changeset - end + def changeset(poll, attrs) do + poll + |> cast(attrs, [:points, :title, :end_time]) + |> validate_required([:points, :title, :end_time]) end end diff --git a/priv/repo/migrations/20211211063946_create_polls.exs b/priv/repo/migrations/20211211063946_create_polls.exs new file mode 100644 index 0000000..a28ec28 --- /dev/null +++ b/priv/repo/migrations/20211211063946_create_polls.exs @@ -0,0 +1,18 @@ +defmodule Diskuy.Repo.Migrations.CreatePolls do + use Ecto.Migration + + def change do + create table(:polls) do + add :points, :integer + add :title, :string + add :end_time, :utc_datetime + add :topic_id, references(:topics, on_delete: :nothing) + add :user_id, references(:users, on_delete: :nothing) + + timestamps() + end + + create index(:polls, [:topic_id]) + create index(:polls, [:user_id]) + end +end diff --git a/priv/repo/migrations/20211211064623_create_choices.exs b/priv/repo/migrations/20211211064623_create_choices.exs new file mode 100644 index 0000000..6f2660e --- /dev/null +++ b/priv/repo/migrations/20211211064623_create_choices.exs @@ -0,0 +1,14 @@ +defmodule Diskuy.Repo.Migrations.CreateChoices do + use Ecto.Migration + + def change do + create table(:choices) do + add :name, :string + add :poll, references(:polls, on_delete: :nothing) + + timestamps() + end + + create index(:choices, [:poll]) + end +end diff --git a/priv/repo/migrations/20211211065116_create_polls.exs b/priv/repo/migrations/20211211065116_create_polls.exs new file mode 100644 index 0000000..7cdfdf9 --- /dev/null +++ b/priv/repo/migrations/20211211065116_create_polls.exs @@ -0,0 +1,19 @@ +defmodule Diskuy.Repo.Migrations.CreatePolls do + use Ecto.Migration + + def change do + create table(:polls) do + add :points, :integer, null: false + add :title, :string, null: false + add :end_time, :utc_datetime, null: false + add :topic_id, references(:topics, on_delete: :delete_all) + add :user_id, references(:users, on_delete: :delete_all) + + timestamps() + end + + create index(:polls, [:topic_id]) + create index(:polls, [:user_id]) + create unique_index(:polls, [:title]) + end +end diff --git a/priv/repo/migrations/20211211065254_create_choices.exs b/priv/repo/migrations/20211211065254_create_choices.exs new file mode 100644 index 0000000..6f2660e --- /dev/null +++ b/priv/repo/migrations/20211211065254_create_choices.exs @@ -0,0 +1,14 @@ +defmodule Diskuy.Repo.Migrations.CreateChoices do + use Ecto.Migration + + def change do + create table(:choices) do + add :name, :string + add :poll, references(:polls, on_delete: :nothing) + + timestamps() + end + + create index(:choices, [:poll]) + end +end diff --git a/test/diskuy/survey_test.exs b/test/diskuy/survey_test.exs new file mode 100644 index 0000000..babed28 --- /dev/null +++ b/test/diskuy/survey_test.exs @@ -0,0 +1,139 @@ +defmodule Diskuy.SurveyTest do + use Diskuy.DataCase + + alias Diskuy.Survey + + describe "polls" do + alias Diskuy.Survey.Poll + + @valid_attrs %{end_time: "2010-04-17T14:00:00Z", points: 42, title: "some title"} + @update_attrs %{end_time: "2011-05-18T15:01:01Z", points: 43, title: "some updated title"} + @invalid_attrs %{end_time: nil, points: nil, title: nil} + + def poll_fixture(attrs \\ %{}) do + {:ok, poll} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_poll() + + poll + end + + test "list_polls/0 returns all polls" do + poll = poll_fixture() + assert Survey.list_polls() == [poll] + end + + test "get_poll!/1 returns the poll with given id" do + poll = poll_fixture() + assert Survey.get_poll!(poll.id) == poll + end + + test "create_poll/1 with valid data creates a poll" do + assert {:ok, %Poll{} = poll} = Survey.create_poll(@valid_attrs) + assert poll.end_time == DateTime.from_naive!(~N[2010-04-17T14:00:00Z], "Etc/UTC") + assert poll.points == 42 + assert poll.title == "some title" + end + + test "create_poll/1 with invalid data returns error change" do + assert {:error, %Ecto.Changeset{}} = Survey.create_poll(@invalid_attrs) + end + + test "update_poll/2 with valid data updates the poll" do + poll = poll_fixture() + assert {:ok, %Poll{} = poll} = Survey.update_poll(poll, @update_attrs) + assert poll.end_time == DateTime.from_naive!(~N[2011-05-18T15:01:01Z], "Etc/UTC") + assert poll.points == 43 + assert poll.title == "some updated title" + end + + test "update_poll/2 with invalid data returns error changeset" do + poll = poll_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_poll(poll, @invalid_attrs) + assert poll == Survey.get_poll!(poll.id) + end + + test "delete_poll/1 deletes the poll" do + poll = poll_fixture() + assert {:ok, %Poll{}} = Survey.delete_poll(poll) + assert_raise Ecto.NoResultsError, fn -> Survey.get_poll!(poll.id) end + end + + test "change_poll/1 returns a poll changeset" do + poll = poll_fixture() + assert %Ecto.Changeset{} = Survey.change_poll(poll) + end + end + + describe "choices" do + alias Diskuy.Survey.Choice + + @valid_attrs %{name: "some name"} + @update_attrs %{name: "some updated name"} + @invalid_attrs %{name: nil} + + setup do + poll = poll_fixture() + {:ok, poll: poll} + end + + def choice_fixture(poll, attrs \\ %{}) do + attrs = Enum.into(attrs, @valid_attrs) + {:ok, choice} = Poll.create_choice(poll, attrs) + + choice + end + + def choice_fixture(attrs \\ %{}) do + {:ok, choice} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_choice() + + choice + end + + test "list_choices/0 returns all choices", %{poll: poll} do + choice = choice_fixture(poll) + assert Survey.list_choices(poll) == [choice] + end + + test "get_choice!/1 returns the choice with given id" do + choice = choice_fixture() + assert Survey.get_choice!(choice.id) == choice + end + + test "create_choice/1 with valid data creates a choice" do + assert {:ok, %Choice{} = choice} = Survey.create_choice(@valid_attrs) + assert choice.name == "some name" + end + + test "create_choice/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Survey.create_choice(@invalid_attrs) + end + + test "update_choice/2 with valid data updates the choice" do + choice = choice_fixture() + assert {:ok, %Choice{} = choice} = Survey.update_choice(choice, @update_attrs) + assert choice.name == "some updated name" + end + + test "update_choice/2 with invalid data returns error changeset" do + choice = choice_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_choice(choice, @invalid_attrs) + assert choice == Survey.get_choice!(choice.id) + end + + test "delete_choice/1 deletes the choice" do + choice = choice_fixture() + assert {:ok, %Choice{}} = Survey.delete_choice(choice) + assert_raise Ecto.NoResultsError, fn -> Survey.get_choice!(choice.id) end + end + + test "change_choice/1 returns a choice changeset" do + choice = choice_fixture() + assert %Ecto.Changeset{} = Survey.change_choice(choice) + end + end +end -- GitLab From 3317825467c30f62294afb29dec631d8b2d5efb3 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 14:10:01 +0700 Subject: [PATCH 07/23] chore: delete migration --- .../migrations/20211211063946_create_polls.exs | 18 ------------------ .../20211211064623_create_choices.exs | 14 -------------- 2 files changed, 32 deletions(-) delete mode 100644 priv/repo/migrations/20211211063946_create_polls.exs delete mode 100644 priv/repo/migrations/20211211064623_create_choices.exs diff --git a/priv/repo/migrations/20211211063946_create_polls.exs b/priv/repo/migrations/20211211063946_create_polls.exs deleted file mode 100644 index a28ec28..0000000 --- a/priv/repo/migrations/20211211063946_create_polls.exs +++ /dev/null @@ -1,18 +0,0 @@ -defmodule Diskuy.Repo.Migrations.CreatePolls do - use Ecto.Migration - - def change do - create table(:polls) do - add :points, :integer - add :title, :string - add :end_time, :utc_datetime - add :topic_id, references(:topics, on_delete: :nothing) - add :user_id, references(:users, on_delete: :nothing) - - timestamps() - end - - create index(:polls, [:topic_id]) - create index(:polls, [:user_id]) - end -end diff --git a/priv/repo/migrations/20211211064623_create_choices.exs b/priv/repo/migrations/20211211064623_create_choices.exs deleted file mode 100644 index 6f2660e..0000000 --- a/priv/repo/migrations/20211211064623_create_choices.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule Diskuy.Repo.Migrations.CreateChoices do - use Ecto.Migration - - def change do - create table(:choices) do - add :name, :string - add :poll, references(:polls, on_delete: :nothing) - - timestamps() - end - - create index(:choices, [:poll]) - end -end -- GitLab From 48625f5768d8339607761afae1548a25bce912bf Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 14:13:02 +0700 Subject: [PATCH 08/23] feat(schema): add phx.gen.context generated Vote schema --- lib/diskuy/survey.ex | 96 +++++++++++++++++++ lib/diskuy/survey/vote.ex | 8 +- .../20211211071242_create_votes.exs | 15 +++ test/diskuy/survey_test.exs | 57 +++++++++++ 4 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 priv/repo/migrations/20211211071242_create_votes.exs diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 8741fd4..d59b8f2 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -199,4 +199,100 @@ defmodule Diskuy.Survey do def change_choice(%Choice{} = choice, attrs \\ %{}) do Choice.changeset(choice, attrs) end + + alias Diskuy.Survey.Vote + + @doc """ + Returns the list of votes. + + ## Examples + + iex> list_votes() + [%Vote{}, ...] + + """ + def list_votes do + Repo.all(Vote) + end + + @doc """ + Gets a single vote. + + Raises `Ecto.NoResultsError` if the Vote does not exist. + + ## Examples + + iex> get_vote!(123) + %Vote{} + + iex> get_vote!(456) + ** (Ecto.NoResultsError) + + """ + def get_vote!(id), do: Repo.get!(Vote, id) + + @doc """ + Creates a vote. + + ## Examples + + iex> create_vote(%{field: value}) + {:ok, %Vote{}} + + iex> create_vote(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_vote(attrs \\ %{}) do + %Vote{} + |> Vote.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a vote. + + ## Examples + + iex> update_vote(vote, %{field: new_value}) + {:ok, %Vote{}} + + iex> update_vote(vote, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_vote(%Vote{} = vote, attrs) do + vote + |> Vote.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a vote. + + ## Examples + + iex> delete_vote(vote) + {:ok, %Vote{}} + + iex> delete_vote(vote) + {:error, %Ecto.Changeset{}} + + """ + def delete_vote(%Vote{} = vote) do + Repo.delete(vote) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking vote changes. + + ## Examples + + iex> change_vote(vote) + %Ecto.Changeset{data: %Vote{}} + + """ + def change_vote(%Vote{} = vote, attrs \\ %{}) do + Vote.changeset(vote, attrs) + end end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index fd13537..eafcb45 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -4,15 +4,15 @@ defmodule Diskuy.Survey.Vote do schema "votes" do field :user_id, :id - field :poll_id, :id field :choice_id, :id timestamps() end @doc false - def changeset(post, attrs) do - post - |> cast(attrs, [:user_id, :points, :poll]) + def changeset(vote, attrs) do + vote + |> cast(attrs, []) + |> validate_required([]) end end diff --git a/priv/repo/migrations/20211211071242_create_votes.exs b/priv/repo/migrations/20211211071242_create_votes.exs new file mode 100644 index 0000000..1de3726 --- /dev/null +++ b/priv/repo/migrations/20211211071242_create_votes.exs @@ -0,0 +1,15 @@ +defmodule Diskuy.Repo.Migrations.CreateVotes do + use Ecto.Migration + + def change do + create table(:votes) do + add :user_id, references(:users, on_delete: :nothing) + add :choice_id, references(:choices, on_delete: :nothing) + + timestamps() + end + + create index(:votes, [:user_id]) + create index(:votes, [:choice_id]) + end +end diff --git a/test/diskuy/survey_test.exs b/test/diskuy/survey_test.exs index babed28..a6a59a1 100644 --- a/test/diskuy/survey_test.exs +++ b/test/diskuy/survey_test.exs @@ -136,4 +136,61 @@ defmodule Diskuy.SurveyTest do assert %Ecto.Changeset{} = Survey.change_choice(choice) end end + + describe "votes" do + alias Diskuy.Survey.Vote + + @valid_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + def vote_fixture(attrs \\ %{}) do + {:ok, vote} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_vote() + + vote + end + + test "list_votes/0 returns all votes" do + vote = vote_fixture() + assert Survey.list_votes() == [vote] + end + + test "get_vote!/1 returns the vote with given id" do + vote = vote_fixture() + assert Survey.get_vote!(vote.id) == vote + end + + test "create_vote/1 with valid data creates a vote" do + assert {:ok, %Vote{} = vote} = Survey.create_vote(@valid_attrs) + end + + test "create_vote/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Survey.create_vote(@invalid_attrs) + end + + test "update_vote/2 with valid data updates the vote" do + vote = vote_fixture() + assert {:ok, %Vote{} = vote} = Survey.update_vote(vote, @update_attrs) + end + + test "update_vote/2 with invalid data returns error changeset" do + vote = vote_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_vote(vote, @invalid_attrs) + assert vote == Survey.get_vote!(vote.id) + end + + test "delete_vote/1 deletes the vote" do + vote = vote_fixture() + assert {:ok, %Vote{}} = Survey.delete_vote(vote) + assert_raise Ecto.NoResultsError, fn -> Survey.get_vote!(vote.id) end + end + + test "change_vote/1 returns a vote changeset" do + vote = vote_fixture() + assert %Ecto.Changeset{} = Survey.change_vote(vote) + end + end end -- GitLab From 1529408c810a1a51c3a959ba529144a8e02a5d46 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 14:21:13 +0700 Subject: [PATCH 09/23] feat(vote): add has_many & belongs_to --- lib/diskuy/survey.ex | 12 +++++++----- lib/diskuy/survey/choice.ex | 1 + lib/diskuy/survey/vote.ex | 2 +- priv/repo/migrations/20211211071242_create_votes.exs | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index d59b8f2..35e06d2 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -146,7 +146,7 @@ defmodule Diskuy.Survey do {:error, %Ecto.Changeset{}} """ - def create_choice(attrs \\ %{}) do + def create_choice(poll, attrs \\ %{}) do %Choice{} |> Ecto.build_assoc(:choices) |> Choice.changeset(attrs) @@ -211,8 +211,9 @@ defmodule Diskuy.Survey do [%Vote{}, ...] """ - def list_votes do - Repo.all(Vote) + def list_votes(choice) do + from(v in Votes, where: [choice_id: ^choice.id], order_by: [asc: :id]) + |> Repo.all() end @doc """ @@ -229,7 +230,7 @@ defmodule Diskuy.Survey do ** (Ecto.NoResultsError) """ - def get_vote!(id), do: Repo.get!(Vote, id) + def get_vote!(choice, id), do: Repo.get_by!(Vote, choice_id: choice.id, id: id) @doc """ Creates a vote. @@ -243,8 +244,9 @@ defmodule Diskuy.Survey do {:error, %Ecto.Changeset{}} """ - def create_vote(attrs \\ %{}) do + def create_vote(choice, attrs \\ %{}) do %Vote{} + |> Ecto.build_assoc(:votes) |> Vote.changeset(attrs) |> Repo.insert() end diff --git a/lib/diskuy/survey/choice.ex b/lib/diskuy/survey/choice.ex index fc159ca..374e9df 100644 --- a/lib/diskuy/survey/choice.ex +++ b/lib/diskuy/survey/choice.ex @@ -5,6 +5,7 @@ defmodule Diskuy.Survey.Choice do schema "choices" do field :name, :string belongs_to :poll, Diskuy.Survey.Poll + has_many :votes, Diskuy.Survey.Vote timestamps() end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index eafcb45..ce5304f 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -4,7 +4,7 @@ defmodule Diskuy.Survey.Vote do schema "votes" do field :user_id, :id - field :choice_id, :id + belongs_to :choice, Diskuy.Survey.Choice timestamps() end diff --git a/priv/repo/migrations/20211211071242_create_votes.exs b/priv/repo/migrations/20211211071242_create_votes.exs index 1de3726..a957f54 100644 --- a/priv/repo/migrations/20211211071242_create_votes.exs +++ b/priv/repo/migrations/20211211071242_create_votes.exs @@ -3,13 +3,14 @@ defmodule Diskuy.Repo.Migrations.CreateVotes do def change do create table(:votes) do - add :user_id, references(:users, on_delete: :nothing) - add :choice_id, references(:choices, on_delete: :nothing) + add :user_id, references(:users, on_delete: :delete_all) + add :choice_id, references(:choices, on_delete: :delete_all) timestamps() end create index(:votes, [:user_id]) create index(:votes, [:choice_id]) + create unique_index(:votes, [:user_id, :user_id, :choice_id]) end end -- GitLab From 3a56933c51c24be09638bb905372cc339cbc148b Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 14:25:45 +0700 Subject: [PATCH 10/23] feat(vote): modify test to adjust the o2m model change --- test/diskuy/survey_test.exs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/test/diskuy/survey_test.exs b/test/diskuy/survey_test.exs index a6a59a1..37fb4cd 100644 --- a/test/diskuy/survey_test.exs +++ b/test/diskuy/survey_test.exs @@ -73,11 +73,6 @@ defmodule Diskuy.SurveyTest do @update_attrs %{name: "some updated name"} @invalid_attrs %{name: nil} - setup do - poll = poll_fixture() - {:ok, poll: poll} - end - def choice_fixture(poll, attrs \\ %{}) do attrs = Enum.into(attrs, @valid_attrs) {:ok, choice} = Poll.create_choice(poll, attrs) @@ -85,6 +80,11 @@ defmodule Diskuy.SurveyTest do choice end + setup do + poll = poll_fixture() + {:ok, poll: poll} + end + def choice_fixture(attrs \\ %{}) do {:ok, choice} = attrs @@ -144,18 +144,21 @@ defmodule Diskuy.SurveyTest do @update_attrs %{} @invalid_attrs %{} - def vote_fixture(attrs \\ %{}) do - {:ok, vote} = - attrs - |> Enum.into(@valid_attrs) - |> Survey.create_vote() + def vote_fixture(choice, attrs \\ %{}) do + attrs = Enum.into(attrs, @valid_attrs) + {:ok, vote} = Choice.create_vote(choice, attrs) - vote + variant end - test "list_votes/0 returns all votes" do - vote = vote_fixture() - assert Survey.list_votes() == [vote] + setup do + choice = choice_fixture() + {:ok, choice: choice} + end + + test "list_votes/0 returns all votes", %{choice: choice} do + vote = vote_fixture(choice) + assert Survey.list_votes(choice) == [vote] end test "get_vote!/1 returns the vote with given id" do -- GitLab From 8ee0670463e7fdb3e3e9c184509260a2b2cc90a9 Mon Sep 17 00:00:00 2001 From: azhar81 Date: Sat, 11 Dec 2021 14:53:28 +0700 Subject: [PATCH 11/23] feat: pembuatan schema untuk komentar --- lib/diskuy/survey/comment.ex | 19 +++++++++++++++++++ .../20211211075121_create_survey_comments.exs | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 lib/diskuy/survey/comment.ex create mode 100644 priv/repo/migrations/20211211075121_create_survey_comments.exs diff --git a/lib/diskuy/survey/comment.ex b/lib/diskuy/survey/comment.ex new file mode 100644 index 0000000..ea614d8 --- /dev/null +++ b/lib/diskuy/survey/comment.ex @@ -0,0 +1,19 @@ +defmodule Diskuy.Survey.Comment do + use Ecto.Schema + import Ecto.Changeset + + schema "survey_comments" do + field :comment, :string + field :user_id, :id + field :poll_id, :id + + timestamps() + end + + @doc false + def changeset(comment, attrs) do + comment + |> cast(attrs, [:comment]) + |> validate_required([:comment]) + end +end diff --git a/priv/repo/migrations/20211211075121_create_survey_comments.exs b/priv/repo/migrations/20211211075121_create_survey_comments.exs new file mode 100644 index 0000000..986ae04 --- /dev/null +++ b/priv/repo/migrations/20211211075121_create_survey_comments.exs @@ -0,0 +1,16 @@ +defmodule Diskuy.Repo.Migrations.CreateSurveyComments do + use Ecto.Migration + + def change do + create table(:survey_comments) do + add :comment, :text + add :user_id, references(:users, on_delete: :nothing) + add :poll_id, references(:polls, on_delete: :nothing) + + timestamps() + end + + create index(:survey_comments, [:user_id]) + create index(:survey_comments, [:poll_id]) + end +end -- GitLab From d4e7368974555e5fa0d2105d8e15b6d29d2661fc Mon Sep 17 00:00:00 2001 From: azhar81 Date: Sat, 11 Dec 2021 19:12:42 +0700 Subject: [PATCH 12/23] feat: api to create comments --- lib/diskuy/survey.ex | 97 +++++++++++++++++++ .../controllers/comment_controller.ex | 43 ++++++++ lib/diskuy_web/router.ex | 2 + lib/diskuy_web/views/comment_view.ex | 17 ++++ test/diskuy/survey_test.exs | 59 +++++++++++ .../controllers/comment_controller_test.exs | 88 +++++++++++++++++ 6 files changed, 306 insertions(+) create mode 100644 lib/diskuy_web/controllers/comment_controller.ex create mode 100644 lib/diskuy_web/views/comment_view.ex create mode 100644 test/diskuy_web/controllers/comment_controller_test.exs diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 35e06d2..64dfb78 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -1,4 +1,5 @@ defmodule Diskuy.Survey do + require Logger @moduledoc """ The Survey context. """ @@ -297,4 +298,100 @@ defmodule Diskuy.Survey do def change_vote(%Vote{} = vote, attrs \\ %{}) do Vote.changeset(vote, attrs) end + + alias Diskuy.Survey.Comment + + @doc """ + Returns the list of survey_comments. + + ## Examples + + iex> list_survey_comments() + [%Comment{}, ...] + + """ + def list_survey_comments do + Repo.all(Comment) + end + + @doc """ + Gets a single comment. + + Raises `Ecto.NoResultsError` if the Comment does not exist. + + ## Examples + + iex> get_comment!(123) + %Comment{} + + iex> get_comment!(456) + ** (Ecto.NoResultsError) + + """ + def get_comment!(id), do: Repo.get!(Comment, id) + + @doc """ + Creates a comment. + + ## Examples + + iex> create_comment(%{field: value}) + {:ok, %Comment{}} + + iex> create_comment(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_comment(attrs \\ %{}) do + %Comment{} + |> Comment.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a comment. + + ## Examples + + iex> update_comment(comment, %{field: new_value}) + {:ok, %Comment{}} + + iex> update_comment(comment, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_comment(%Comment{} = comment, attrs) do + comment + |> Comment.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a comment. + + ## Examples + + iex> delete_comment(comment) + {:ok, %Comment{}} + + iex> delete_comment(comment) + {:error, %Ecto.Changeset{}} + + """ + def delete_comment(%Comment{} = comment) do + Repo.delete(comment) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking comment changes. + + ## Examples + + iex> change_comment(comment) + %Ecto.Changeset{data: %Comment{}} + + """ + def change_comment(%Comment{} = comment, attrs \\ %{}) do + Comment.changeset(comment, attrs) + end end diff --git a/lib/diskuy_web/controllers/comment_controller.ex b/lib/diskuy_web/controllers/comment_controller.ex new file mode 100644 index 0000000..139e1b2 --- /dev/null +++ b/lib/diskuy_web/controllers/comment_controller.ex @@ -0,0 +1,43 @@ +defmodule DiskuyWeb.CommentController do + use DiskuyWeb, :controller + + alias Diskuy.Survey + alias Diskuy.Survey.Comment + + action_fallback DiskuyWeb.FallbackController + + def index(conn, _params) do + survey_comments = Survey.list_survey_comments() + render(conn, "index.json", survey_comments: survey_comments) + end + + def create(conn, %{"comment" => comment_params}) do + with {:ok, %Comment{} = comment} <- Survey.create_comment(comment_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.comment_path(conn, :show, comment)) + |> render("show.json", comment: comment) + end + end + + def show(conn, %{"id" => id}) do + comment = Survey.get_comment!(id) + render(conn, "show.json", comment: comment) + end + + def update(conn, %{"id" => id, "comment" => comment_params}) do + comment = Survey.get_comment!(id) + + with {:ok, %Comment{} = comment} <- Survey.update_comment(comment, comment_params) do + render(conn, "show.json", comment: comment) + end + end + + def delete(conn, %{"id" => id}) do + comment = Survey.get_comment!(id) + + with {:ok, %Comment{}} <- Survey.delete_comment(comment) do + send_resp(conn, :no_content, "") + end + end +end diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 269ac2c..48fb275 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -51,6 +51,8 @@ defmodule DiskuyWeb.Router do get "/users/name/:name", UserController, :show_by_username options "/users/name/:name", UserController, :options + resources "/comment", CommentController + resources "/topics", TopicController, except: [:new, :edit, :create, :update, :delete] options "/topics", TopicController, :options options "/topics/:id", TopicController, :options diff --git a/lib/diskuy_web/views/comment_view.ex b/lib/diskuy_web/views/comment_view.ex new file mode 100644 index 0000000..9015360 --- /dev/null +++ b/lib/diskuy_web/views/comment_view.ex @@ -0,0 +1,17 @@ +defmodule DiskuyWeb.CommentView do + use DiskuyWeb, :view + alias DiskuyWeb.CommentView + + def render("index.json", %{survey_comments: survey_comments}) do + %{data: render_many(survey_comments, CommentView, "comment.json")} + end + + def render("show.json", %{comment: comment}) do + %{data: render_one(comment, CommentView, "comment.json")} + end + + def render("comment.json", %{comment: comment}) do + %{id: comment.id, + comment: comment.comment} + end +end diff --git a/test/diskuy/survey_test.exs b/test/diskuy/survey_test.exs index 37fb4cd..985196a 100644 --- a/test/diskuy/survey_test.exs +++ b/test/diskuy/survey_test.exs @@ -196,4 +196,63 @@ defmodule Diskuy.SurveyTest do assert %Ecto.Changeset{} = Survey.change_vote(vote) end end + + describe "survey_comments" do + alias Diskuy.Survey.Comment + + @valid_attrs %{comment: "some comment"} + @update_attrs %{comment: "some updated comment"} + @invalid_attrs %{comment: nil} + + def comment_fixture(attrs \\ %{}) do + {:ok, comment} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_comment() + + comment + end + + test "list_survey_comments/0 returns all survey_comments" do + comment = comment_fixture() + assert Survey.list_survey_comments() == [comment] + end + + test "get_comment!/1 returns the comment with given id" do + comment = comment_fixture() + assert Survey.get_comment!(comment.id) == comment + end + + test "create_comment/1 with valid data creates a comment" do + assert {:ok, %Comment{} = comment} = Survey.create_comment(@valid_attrs) + assert comment.comment == "some comment" + end + + test "create_comment/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Survey.create_comment(@invalid_attrs) + end + + test "update_comment/2 with valid data updates the comment" do + comment = comment_fixture() + assert {:ok, %Comment{} = comment} = Survey.update_comment(comment, @update_attrs) + assert comment.comment == "some updated comment" + end + + test "update_comment/2 with invalid data returns error changeset" do + comment = comment_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_comment(comment, @invalid_attrs) + assert comment == Survey.get_comment!(comment.id) + end + + test "delete_comment/1 deletes the comment" do + comment = comment_fixture() + assert {:ok, %Comment{}} = Survey.delete_comment(comment) + assert_raise Ecto.NoResultsError, fn -> Survey.get_comment!(comment.id) end + end + + test "change_comment/1 returns a comment changeset" do + comment = comment_fixture() + assert %Ecto.Changeset{} = Survey.change_comment(comment) + end + end end diff --git a/test/diskuy_web/controllers/comment_controller_test.exs b/test/diskuy_web/controllers/comment_controller_test.exs new file mode 100644 index 0000000..bf4a642 --- /dev/null +++ b/test/diskuy_web/controllers/comment_controller_test.exs @@ -0,0 +1,88 @@ +defmodule DiskuyWeb.CommentControllerTest do + use DiskuyWeb.ConnCase + + alias Diskuy.Survey + alias Diskuy.Survey.Comment + + @create_attrs %{ + comment: "some comment" + } + @update_attrs %{ + comment: "some updated comment" + } + @invalid_attrs %{comment: nil} + + def fixture(:comment) do + {:ok, comment} = Survey.create_comment(@create_attrs) + comment + end + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all survey_comments", %{conn: conn} do + conn = get(conn, Routes.comment_path(conn, :index)) + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create comment" do + test "renders comment when data is valid", %{conn: conn} do + conn = post(conn, Routes.comment_path(conn, :create), comment: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, Routes.comment_path(conn, :show, id)) + + assert %{ + "id" => id, + "comment" => "some comment" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.comment_path(conn, :create), comment: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update comment" do + setup [:create_comment] + + test "renders comment when data is valid", %{conn: conn, comment: %Comment{id: id} = comment} do + conn = put(conn, Routes.comment_path(conn, :update, comment), comment: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, Routes.comment_path(conn, :show, id)) + + assert %{ + "id" => id, + "comment" => "some updated comment" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, comment: comment} do + conn = put(conn, Routes.comment_path(conn, :update, comment), comment: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete comment" do + setup [:create_comment] + + test "deletes chosen comment", %{conn: conn, comment: comment} do + conn = delete(conn, Routes.comment_path(conn, :delete, comment)) + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, Routes.comment_path(conn, :show, comment)) + end + end + end + + defp create_comment(_) do + comment = fixture(:comment) + %{comment: comment} + end +end -- GitLab From b4d0db9025e61f19f7b3543d724a5645b59471ce Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 19:37:43 +0700 Subject: [PATCH 13/23] feat(poll): generate controller --- lib/diskuy_web/controllers/poll_controller.ex | 43 +++++++++ lib/diskuy_web/views/poll_view.ex | 19 ++++ .../controllers/poll_controller_test.exs | 96 +++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 lib/diskuy_web/controllers/poll_controller.ex create mode 100644 lib/diskuy_web/views/poll_view.ex create mode 100644 test/diskuy_web/controllers/poll_controller_test.exs diff --git a/lib/diskuy_web/controllers/poll_controller.ex b/lib/diskuy_web/controllers/poll_controller.ex new file mode 100644 index 0000000..9ae8512 --- /dev/null +++ b/lib/diskuy_web/controllers/poll_controller.ex @@ -0,0 +1,43 @@ +defmodule DiskuyWeb.PollController do + use DiskuyWeb, :controller + + alias Diskuy.Survey + alias Diskuy.Survey.Poll + + action_fallback DiskuyWeb.FallbackController + + def index(conn, _params) do + polls = Survey.list_polls() + render(conn, "index.json", polls: polls) + end + + def create(conn, %{"poll" => poll_params}) do + with {:ok, %Poll{} = poll} <- Survey.create_poll(poll_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.poll_path(conn, :show, poll)) + |> render("show.json", poll: poll) + end + end + + def show(conn, %{"id" => id}) do + poll = Survey.get_poll!(id) + render(conn, "show.json", poll: poll) + end + + def update(conn, %{"id" => id, "poll" => poll_params}) do + poll = Survey.get_poll!(id) + + with {:ok, %Poll{} = poll} <- Survey.update_poll(poll, poll_params) do + render(conn, "show.json", poll: poll) + end + end + + def delete(conn, %{"id" => id}) do + poll = Survey.get_poll!(id) + + with {:ok, %Poll{}} <- Survey.delete_poll(poll) do + send_resp(conn, :no_content, "") + end + end +end diff --git a/lib/diskuy_web/views/poll_view.ex b/lib/diskuy_web/views/poll_view.ex new file mode 100644 index 0000000..6e55d67 --- /dev/null +++ b/lib/diskuy_web/views/poll_view.ex @@ -0,0 +1,19 @@ +defmodule DiskuyWeb.PollView do + use DiskuyWeb, :view + alias DiskuyWeb.PollView + + def render("index.json", %{polls: polls}) do + %{data: render_many(polls, PollView, "poll.json")} + end + + def render("show.json", %{poll: poll}) do + %{data: render_one(poll, PollView, "poll.json")} + end + + def render("poll.json", %{poll: poll}) do + %{id: poll.id, + points: poll.points, + title: poll.title, + end_time: poll.end_time} + end +end diff --git a/test/diskuy_web/controllers/poll_controller_test.exs b/test/diskuy_web/controllers/poll_controller_test.exs new file mode 100644 index 0000000..5f131b2 --- /dev/null +++ b/test/diskuy_web/controllers/poll_controller_test.exs @@ -0,0 +1,96 @@ +defmodule DiskuyWeb.PollControllerTest do + use DiskuyWeb.ConnCase + + alias Diskuy.Survey + alias Diskuy.Survey.Poll + + @create_attrs %{ + end_time: "2010-04-17T14:00:00Z", + points: 42, + title: "some title" + } + @update_attrs %{ + end_time: "2011-05-18T15:01:01Z", + points: 43, + title: "some updated title" + } + @invalid_attrs %{end_time: nil, points: nil, title: nil} + + def fixture(:poll) do + {:ok, poll} = Survey.create_poll(@create_attrs) + poll + end + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all polls", %{conn: conn} do + conn = get(conn, Routes.poll_path(conn, :index)) + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create poll" do + test "renders poll when data is valid", %{conn: conn} do + conn = post(conn, Routes.poll_path(conn, :create), poll: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, Routes.poll_path(conn, :show, id)) + + assert %{ + "id" => id, + "end_time" => "2010-04-17T14:00:00Z", + "points" => 42, + "title" => "some title" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.poll_path(conn, :create), poll: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update poll" do + setup [:create_poll] + + test "renders poll when data is valid", %{conn: conn, poll: %Poll{id: id} = poll} do + conn = put(conn, Routes.poll_path(conn, :update, poll), poll: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, Routes.poll_path(conn, :show, id)) + + assert %{ + "id" => id, + "end_time" => "2011-05-18T15:01:01Z", + "points" => 43, + "title" => "some updated title" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, poll: poll} do + conn = put(conn, Routes.poll_path(conn, :update, poll), poll: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete poll" do + setup [:create_poll] + + test "deletes chosen poll", %{conn: conn, poll: poll} do + conn = delete(conn, Routes.poll_path(conn, :delete, poll)) + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, Routes.poll_path(conn, :show, poll)) + end + end + end + + defp create_poll(_) do + poll = fixture(:poll) + %{poll: poll} + end +end -- GitLab From e208a115a1727e9ce9750f299d3dd4fdfc938c30 Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 19:40:21 +0700 Subject: [PATCH 14/23] feat(vote): generate controller & view --- lib/diskuy_web/controllers/vote_controller.ex | 43 ++++++++++ lib/diskuy_web/views/vote_view.ex | 16 ++++ .../controllers/vote_controller_test.exs | 86 +++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 lib/diskuy_web/controllers/vote_controller.ex create mode 100644 lib/diskuy_web/views/vote_view.ex create mode 100644 test/diskuy_web/controllers/vote_controller_test.exs diff --git a/lib/diskuy_web/controllers/vote_controller.ex b/lib/diskuy_web/controllers/vote_controller.ex new file mode 100644 index 0000000..bc5235e --- /dev/null +++ b/lib/diskuy_web/controllers/vote_controller.ex @@ -0,0 +1,43 @@ +defmodule DiskuyWeb.VoteController do + use DiskuyWeb, :controller + + alias Diskuy.Survey + alias Diskuy.Survey.Vote + + action_fallback DiskuyWeb.FallbackController + + def index(conn, _params) do + votes = Survey.list_votes() + render(conn, "index.json", votes: votes) + end + + def create(conn, %{"vote" => vote_params}) do + with {:ok, %Vote{} = vote} <- Survey.create_vote(vote_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.vote_path(conn, :show, vote)) + |> render("show.json", vote: vote) + end + end + + def show(conn, %{"id" => id}) do + vote = Survey.get_vote!(id) + render(conn, "show.json", vote: vote) + end + + def update(conn, %{"id" => id, "vote" => vote_params}) do + vote = Survey.get_vote!(id) + + with {:ok, %Vote{} = vote} <- Survey.update_vote(vote, vote_params) do + render(conn, "show.json", vote: vote) + end + end + + def delete(conn, %{"id" => id}) do + vote = Survey.get_vote!(id) + + with {:ok, %Vote{}} <- Survey.delete_vote(vote) do + send_resp(conn, :no_content, "") + end + end +end diff --git a/lib/diskuy_web/views/vote_view.ex b/lib/diskuy_web/views/vote_view.ex new file mode 100644 index 0000000..9acf185 --- /dev/null +++ b/lib/diskuy_web/views/vote_view.ex @@ -0,0 +1,16 @@ +defmodule DiskuyWeb.VoteView do + use DiskuyWeb, :view + alias DiskuyWeb.VoteView + + def render("index.json", %{votes: votes}) do + %{data: render_many(votes, VoteView, "vote.json")} + end + + def render("show.json", %{vote: vote}) do + %{data: render_one(vote, VoteView, "vote.json")} + end + + def render("vote.json", %{vote: vote}) do + %{id: vote.id} + end +end diff --git a/test/diskuy_web/controllers/vote_controller_test.exs b/test/diskuy_web/controllers/vote_controller_test.exs new file mode 100644 index 0000000..fba86fc --- /dev/null +++ b/test/diskuy_web/controllers/vote_controller_test.exs @@ -0,0 +1,86 @@ +defmodule DiskuyWeb.VoteControllerTest do + use DiskuyWeb.ConnCase + + alias Diskuy.Survey + alias Diskuy.Survey.Vote + + @create_attrs %{ + + } + @update_attrs %{ + + } + @invalid_attrs %{} + + def fixture(:vote) do + {:ok, vote} = Survey.create_vote(@create_attrs) + vote + end + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all votes", %{conn: conn} do + conn = get(conn, Routes.vote_path(conn, :index)) + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create vote" do + test "renders vote when data is valid", %{conn: conn} do + conn = post(conn, Routes.vote_path(conn, :create), vote: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, Routes.vote_path(conn, :show, id)) + + assert %{ + "id" => id + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.vote_path(conn, :create), vote: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update vote" do + setup [:create_vote] + + test "renders vote when data is valid", %{conn: conn, vote: %Vote{id: id} = vote} do + conn = put(conn, Routes.vote_path(conn, :update, vote), vote: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, Routes.vote_path(conn, :show, id)) + + assert %{ + "id" => id + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, vote: vote} do + conn = put(conn, Routes.vote_path(conn, :update, vote), vote: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete vote" do + setup [:create_vote] + + test "deletes chosen vote", %{conn: conn, vote: vote} do + conn = delete(conn, Routes.vote_path(conn, :delete, vote)) + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, Routes.vote_path(conn, :show, vote)) + end + end + end + + defp create_vote(_) do + vote = fixture(:vote) + %{vote: vote} + end +end -- GitLab From 02a732e909cff9c4d26eeab71d81ecf8d13d1f1b Mon Sep 17 00:00:00 2001 From: Fahdii Ajmalal Fikrie Date: Sat, 11 Dec 2021 19:42:04 +0700 Subject: [PATCH 15/23] feat(choice): add choice controller & view --- .../controllers/choice_controller.ex | 43 +++++++++ lib/diskuy_web/views/choice_view.ex | 17 ++++ .../controllers/choice_controller_test.exs | 88 +++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 lib/diskuy_web/controllers/choice_controller.ex create mode 100644 lib/diskuy_web/views/choice_view.ex create mode 100644 test/diskuy_web/controllers/choice_controller_test.exs diff --git a/lib/diskuy_web/controllers/choice_controller.ex b/lib/diskuy_web/controllers/choice_controller.ex new file mode 100644 index 0000000..57922fd --- /dev/null +++ b/lib/diskuy_web/controllers/choice_controller.ex @@ -0,0 +1,43 @@ +defmodule DiskuyWeb.ChoiceController do + use DiskuyWeb, :controller + + alias Diskuy.Survey + alias Diskuy.Survey.Choice + + action_fallback DiskuyWeb.FallbackController + + def index(conn, _params) do + choices = Survey.list_choices() + render(conn, "index.json", choices: choices) + end + + def create(conn, %{"choice" => choice_params}) do + with {:ok, %Choice{} = choice} <- Survey.create_choice(choice_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.choice_path(conn, :show, choice)) + |> render("show.json", choice: choice) + end + end + + def show(conn, %{"id" => id}) do + choice = Survey.get_choice!(id) + render(conn, "show.json", choice: choice) + end + + def update(conn, %{"id" => id, "choice" => choice_params}) do + choice = Survey.get_choice!(id) + + with {:ok, %Choice{} = choice} <- Survey.update_choice(choice, choice_params) do + render(conn, "show.json", choice: choice) + end + end + + def delete(conn, %{"id" => id}) do + choice = Survey.get_choice!(id) + + with {:ok, %Choice{}} <- Survey.delete_choice(choice) do + send_resp(conn, :no_content, "") + end + end +end diff --git a/lib/diskuy_web/views/choice_view.ex b/lib/diskuy_web/views/choice_view.ex new file mode 100644 index 0000000..09f8a47 --- /dev/null +++ b/lib/diskuy_web/views/choice_view.ex @@ -0,0 +1,17 @@ +defmodule DiskuyWeb.ChoiceView do + use DiskuyWeb, :view + alias DiskuyWeb.ChoiceView + + def render("index.json", %{choices: choices}) do + %{data: render_many(choices, ChoiceView, "choice.json")} + end + + def render("show.json", %{choice: choice}) do + %{data: render_one(choice, ChoiceView, "choice.json")} + end + + def render("choice.json", %{choice: choice}) do + %{id: choice.id, + name: choice.name} + end +end diff --git a/test/diskuy_web/controllers/choice_controller_test.exs b/test/diskuy_web/controllers/choice_controller_test.exs new file mode 100644 index 0000000..e6dd8b9 --- /dev/null +++ b/test/diskuy_web/controllers/choice_controller_test.exs @@ -0,0 +1,88 @@ +defmodule DiskuyWeb.ChoiceControllerTest do + use DiskuyWeb.ConnCase + + alias Diskuy.Survey + alias Diskuy.Survey.Choice + + @create_attrs %{ + name: "some name" + } + @update_attrs %{ + name: "some updated name" + } + @invalid_attrs %{name: nil} + + def fixture(:choice) do + {:ok, choice} = Survey.create_choice(@create_attrs) + choice + end + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all choices", %{conn: conn} do + conn = get(conn, Routes.choice_path(conn, :index)) + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create choice" do + test "renders choice when data is valid", %{conn: conn} do + conn = post(conn, Routes.choice_path(conn, :create), choice: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, Routes.choice_path(conn, :show, id)) + + assert %{ + "id" => id, + "name" => "some name" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.choice_path(conn, :create), choice: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update choice" do + setup [:create_choice] + + test "renders choice when data is valid", %{conn: conn, choice: %Choice{id: id} = choice} do + conn = put(conn, Routes.choice_path(conn, :update, choice), choice: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, Routes.choice_path(conn, :show, id)) + + assert %{ + "id" => id, + "name" => "some updated name" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, choice: choice} do + conn = put(conn, Routes.choice_path(conn, :update, choice), choice: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete choice" do + setup [:create_choice] + + test "deletes chosen choice", %{conn: conn, choice: choice} do + conn = delete(conn, Routes.choice_path(conn, :delete, choice)) + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, Routes.choice_path(conn, :show, choice)) + end + end + end + + defp create_choice(_) do + choice = fixture(:choice) + %{choice: choice} + end +end -- GitLab From 627f283725da7885692a661fc69d3b03c93ed761 Mon Sep 17 00:00:00 2001 From: azhar81 Date: Sat, 11 Dec 2021 22:18:11 +0700 Subject: [PATCH 16/23] feat: api for polls --- lib/diskuy/survey/poll.ex | 4 ++-- lib/diskuy_web/controllers/poll_controller.ex | 10 +++++++++- lib/diskuy_web/router.ex | 5 ++++- lib/diskuy_web/views/poll_view.ex | 8 +++++++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex index 12b1955..b25f86c 100644 --- a/lib/diskuy/survey/poll.ex +++ b/lib/diskuy/survey/poll.ex @@ -16,7 +16,7 @@ defmodule Diskuy.Survey.Poll do @doc false def changeset(poll, attrs) do poll - |> cast(attrs, [:points, :title, :end_time]) - |> validate_required([:points, :title, :end_time]) + |> cast(attrs, [:points, :title, :end_time, :topic_id, :user_id]) + |> validate_required([:points, :title, :end_time, :topic_id, :user_id]) end end diff --git a/lib/diskuy_web/controllers/poll_controller.ex b/lib/diskuy_web/controllers/poll_controller.ex index 9ae8512..f1565fa 100644 --- a/lib/diskuy_web/controllers/poll_controller.ex +++ b/lib/diskuy_web/controllers/poll_controller.ex @@ -1,4 +1,5 @@ defmodule DiskuyWeb.PollController do + require Logger use DiskuyWeb, :controller alias Diskuy.Survey @@ -12,7 +13,8 @@ defmodule DiskuyWeb.PollController do end def create(conn, %{"poll" => poll_params}) do - with {:ok, %Poll{} = poll} <- Survey.create_poll(poll_params) do + new_params = put_user_id(conn, %{"poll" => poll_params}) + with {:ok, %Poll{} = poll} <- Survey.create_poll(new_params) do conn |> put_status(:created) |> put_resp_header("location", Routes.poll_path(conn, :show, poll)) @@ -40,4 +42,10 @@ defmodule DiskuyWeb.PollController do send_resp(conn, :no_content, "") end end + + defp put_user_id(conn, %{"poll" => poll_params}) do + current_user = Guardian.Plug.current_resource(conn) + new_params = Map.put(poll_params, "user_id", current_user.id) + new_params + end end diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 48fb275..133ae68 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -40,6 +40,7 @@ defmodule DiskuyWeb.Router do get "/post/checklike/:id", PostLikeController, :check_like options "/post/checklike/:id", PostLikeController, :options + resources "survey", PollController, except: [:new, :edit, :show, :index] end scope "/api", DiskuyWeb do @@ -86,7 +87,9 @@ defmodule DiskuyWeb.Router do # post "/users/signin", UserController, :signin # options "/users/signin", PostController, :options - + resources "/survey", PollController, except: [:new, :edit, :create, :update, :delete] + options "/survey", PollController, :options + options "/survey/:id", PollController, :options end diff --git a/lib/diskuy_web/views/poll_view.ex b/lib/diskuy_web/views/poll_view.ex index 6e55d67..5aaf560 100644 --- a/lib/diskuy_web/views/poll_view.ex +++ b/lib/diskuy_web/views/poll_view.ex @@ -1,6 +1,7 @@ defmodule DiskuyWeb.PollView do use DiskuyWeb, :view alias DiskuyWeb.PollView + alias Diskuy.Account def render("index.json", %{polls: polls}) do %{data: render_many(polls, PollView, "poll.json")} @@ -11,9 +12,14 @@ defmodule DiskuyWeb.PollView do end def render("poll.json", %{poll: poll}) do + user = Account.get_user!(poll.user_id) %{id: poll.id, points: poll.points, title: poll.title, - end_time: poll.end_time} + end_time: poll.end_time, + topic_id: poll.topic_id, + user_id: poll.user_id, + username: user.username + } end end -- GitLab From ecce88906d3a3e2ab659634b43487da78bb01c1a Mon Sep 17 00:00:00 2001 From: azhar81 Date: Sat, 11 Dec 2021 22:58:45 +0700 Subject: [PATCH 17/23] feat: comment API --- lib/diskuy/survey/comment.ex | 4 ++-- lib/diskuy/survey/vote.ex | 4 ++-- lib/diskuy_web/controllers/comment_controller.ex | 11 ++++++++++- lib/diskuy_web/router.ex | 10 +++++++--- lib/diskuy_web/views/comment_view.ex | 8 +++++++- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/diskuy/survey/comment.ex b/lib/diskuy/survey/comment.ex index ea614d8..1ceb906 100644 --- a/lib/diskuy/survey/comment.ex +++ b/lib/diskuy/survey/comment.ex @@ -13,7 +13,7 @@ defmodule Diskuy.Survey.Comment do @doc false def changeset(comment, attrs) do comment - |> cast(attrs, [:comment]) - |> validate_required([:comment]) + |> cast(attrs, [:comment, :user_id, :poll_id]) + |> validate_required([:comment, :user_id, :poll_id]) end end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index ce5304f..23b344e 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -12,7 +12,7 @@ defmodule Diskuy.Survey.Vote do @doc false def changeset(vote, attrs) do vote - |> cast(attrs, []) - |> validate_required([]) + |> cast(attrs, [:user_id]) + |> validate_required([:user_id]) end end diff --git a/lib/diskuy_web/controllers/comment_controller.ex b/lib/diskuy_web/controllers/comment_controller.ex index 139e1b2..14fef84 100644 --- a/lib/diskuy_web/controllers/comment_controller.ex +++ b/lib/diskuy_web/controllers/comment_controller.ex @@ -1,4 +1,5 @@ defmodule DiskuyWeb.CommentController do + require Logger use DiskuyWeb, :controller alias Diskuy.Survey @@ -12,7 +13,9 @@ defmodule DiskuyWeb.CommentController do end def create(conn, %{"comment" => comment_params}) do - with {:ok, %Comment{} = comment} <- Survey.create_comment(comment_params) do + new_params = put_info(conn, %{"comment" => comment_params}) + Logger.debug "params: #{inspect(new_params)}" + with {:ok, %Comment{} = comment} <- Survey.create_comment(new_params) do conn |> put_status(:created) |> put_resp_header("location", Routes.comment_path(conn, :show, comment)) @@ -40,4 +43,10 @@ defmodule DiskuyWeb.CommentController do send_resp(conn, :no_content, "") end end + + defp put_info(conn, %{"comment" => comment_params}) do + current_user = Guardian.Plug.current_resource(conn) + new_params = Map.put(comment_params, "user_id", current_user.id) + new_params + end end diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 133ae68..9912e10 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -40,7 +40,9 @@ defmodule DiskuyWeb.Router do get "/post/checklike/:id", PostLikeController, :check_like options "/post/checklike/:id", PostLikeController, :options - resources "survey", PollController, except: [:new, :edit, :show, :index] + resources "/survey", PollController, except: [:new, :edit, :show, :index] + + resources "/comment", CommentController, except: [:new, :edit, :show, :index] end scope "/api", DiskuyWeb do @@ -52,8 +54,6 @@ defmodule DiskuyWeb.Router do get "/users/name/:name", UserController, :show_by_username options "/users/name/:name", UserController, :options - resources "/comment", CommentController - resources "/topics", TopicController, except: [:new, :edit, :create, :update, :delete] options "/topics", TopicController, :options options "/topics/:id", TopicController, :options @@ -91,6 +91,10 @@ defmodule DiskuyWeb.Router do options "/survey", PollController, :options options "/survey/:id", PollController, :options + resources "/comment", CommentController, except: [:new, :edit, :create, :update, :delete] + options "/comment", CommentController, :options + options "/comment/:id", CommentController, :options + end scope "/api/auth", DiskuyWeb do diff --git a/lib/diskuy_web/views/comment_view.ex b/lib/diskuy_web/views/comment_view.ex index 9015360..d154d2e 100644 --- a/lib/diskuy_web/views/comment_view.ex +++ b/lib/diskuy_web/views/comment_view.ex @@ -1,6 +1,7 @@ defmodule DiskuyWeb.CommentView do use DiskuyWeb, :view alias DiskuyWeb.CommentView + alias Diskuy.Account def render("index.json", %{survey_comments: survey_comments}) do %{data: render_many(survey_comments, CommentView, "comment.json")} @@ -11,7 +12,12 @@ defmodule DiskuyWeb.CommentView do end def render("comment.json", %{comment: comment}) do + user = Account.get_user!(comment.user_id) %{id: comment.id, - comment: comment.comment} + user_id: comment.user_id, + poll_id: comment.poll_id, + username: user.username, + comment: comment.comment + } end end -- GitLab From 970c9aafe4dbcd5d4ab14a86b1d5cb7953ee4ffc Mon Sep 17 00:00:00 2001 From: azhar81 Date: Sun, 12 Dec 2021 19:03:00 +0700 Subject: [PATCH 18/23] chore: delete debug lines --- lib/diskuy/survey.ex | 1 - lib/diskuy_web/controllers/comment_controller.ex | 2 -- lib/diskuy_web/controllers/poll_controller.ex | 1 - 3 files changed, 4 deletions(-) diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 64dfb78..053fac8 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -1,5 +1,4 @@ defmodule Diskuy.Survey do - require Logger @moduledoc """ The Survey context. """ diff --git a/lib/diskuy_web/controllers/comment_controller.ex b/lib/diskuy_web/controllers/comment_controller.ex index 14fef84..d6a4f9a 100644 --- a/lib/diskuy_web/controllers/comment_controller.ex +++ b/lib/diskuy_web/controllers/comment_controller.ex @@ -1,5 +1,4 @@ defmodule DiskuyWeb.CommentController do - require Logger use DiskuyWeb, :controller alias Diskuy.Survey @@ -14,7 +13,6 @@ defmodule DiskuyWeb.CommentController do def create(conn, %{"comment" => comment_params}) do new_params = put_info(conn, %{"comment" => comment_params}) - Logger.debug "params: #{inspect(new_params)}" with {:ok, %Comment{} = comment} <- Survey.create_comment(new_params) do conn |> put_status(:created) diff --git a/lib/diskuy_web/controllers/poll_controller.ex b/lib/diskuy_web/controllers/poll_controller.ex index f1565fa..c209cf7 100644 --- a/lib/diskuy_web/controllers/poll_controller.ex +++ b/lib/diskuy_web/controllers/poll_controller.ex @@ -1,5 +1,4 @@ defmodule DiskuyWeb.PollController do - require Logger use DiskuyWeb, :controller alias Diskuy.Survey -- GitLab From 292addb49d5a4203d58a6781999b7c56c0ec4efe Mon Sep 17 00:00:00 2001 From: azhar81 Date: Mon, 13 Dec 2021 20:53:03 +0700 Subject: [PATCH 19/23] feat: list comments of poll --- lib/diskuy/survey.ex | 5 +++++ lib/diskuy_web/controllers/comment_controller.ex | 6 ++++++ lib/diskuy_web/router.ex | 1 + lib/diskuy_web/views/comment_view.ex | 2 ++ 4 files changed, 14 insertions(+) diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 053fac8..7b68645 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -393,4 +393,9 @@ defmodule Diskuy.Survey do def change_comment(%Comment{} = comment, attrs \\ %{}) do Comment.changeset(comment, attrs) end + + def list_poll_comments(%Poll{} = poll) do + query = from(Comment, where: [poll_id: ^poll.id]) + Repo.all(query) + end end diff --git a/lib/diskuy_web/controllers/comment_controller.ex b/lib/diskuy_web/controllers/comment_controller.ex index d6a4f9a..622d7e0 100644 --- a/lib/diskuy_web/controllers/comment_controller.ex +++ b/lib/diskuy_web/controllers/comment_controller.ex @@ -42,6 +42,12 @@ defmodule DiskuyWeb.CommentController do end end + def get_poll_comments(conn, %{"id" => id}) do + poll = Survey.get_poll!(id) + comments = Survey.list_poll_comments(poll) + render(conn, "index.json", survey_comments: comments) + end + defp put_info(conn, %{"comment" => comment_params}) do current_user = Guardian.Plug.current_resource(conn) new_params = Map.put(comment_params, "user_id", current_user.id) diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 9912e10..97dbd0a 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -41,6 +41,7 @@ defmodule DiskuyWeb.Router do options "/post/checklike/:id", PostLikeController, :options resources "/survey", PollController, except: [:new, :edit, :show, :index] + get "/survey/:id/comments", CommentController, :get_poll_comments resources "/comment", CommentController, except: [:new, :edit, :show, :index] end diff --git a/lib/diskuy_web/views/comment_view.ex b/lib/diskuy_web/views/comment_view.ex index d154d2e..7ef8866 100644 --- a/lib/diskuy_web/views/comment_view.ex +++ b/lib/diskuy_web/views/comment_view.ex @@ -1,9 +1,11 @@ defmodule DiskuyWeb.CommentView do + require Logger use DiskuyWeb, :view alias DiskuyWeb.CommentView alias Diskuy.Account def render("index.json", %{survey_comments: survey_comments}) do + Logger.debug "query: #{inspect(survey_comments)}" %{data: render_many(survey_comments, CommentView, "comment.json")} end -- GitLab From 39416c92583ced7ae801ce73cfc906815a42ce2f Mon Sep 17 00:00:00 2001 From: azhar81 Date: Thu, 30 Dec 2021 19:31:48 +0700 Subject: [PATCH 20/23] feat: api for choices --- config/dev.exs | 3 +- lib/diskuy/survey.ex | 227 +++++++++--------- lib/diskuy/survey/choice.ex | 9 +- lib/diskuy/survey/poll.ex | 1 - lib/diskuy/survey/vote.ex | 7 +- .../controllers/choice_controller.ex | 28 ++- lib/diskuy_web/router.ex | 9 +- lib/diskuy_web/views/choice_view.ex | 4 +- lib/diskuy_web/views/comment_view.ex | 2 - lib/diskuy_web/views/poll_view.ex | 7 +- ....exs => 20211229120501_create_choices.exs} | 6 +- ...es.exs => 20211229121200_create_votes.exs} | 6 +- test/diskuy/survey_test.exs | 116 +++++++++ .../controllers/choice_controller_test.exs | 10 +- 14 files changed, 291 insertions(+), 144 deletions(-) rename priv/repo/migrations/{20211211065254_create_choices.exs => 20211229120501_create_choices.exs} (55%) rename priv/repo/migrations/{20211211071242_create_votes.exs => 20211229121200_create_votes.exs} (52%) diff --git a/config/dev.exs b/config/dev.exs index 30476c0..fccccc1 100755 --- a/config/dev.exs +++ b/config/dev.exs @@ -7,7 +7,8 @@ config :diskuy, Diskuy.Repo, database: "diskuy_dev", hostname: "localhost", show_sensitive_data_on_connection_error: true, - pool_size: 10 + pool_size: 10, + log: false # For development, we disable any cache and enable # debugging and code reloading. diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 7b68645..87f513b 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -102,6 +102,107 @@ defmodule Diskuy.Survey do Poll.changeset(poll, attrs) end + alias Diskuy.Survey.Comment + + @doc """ + Returns the list of survey_comments. + + ## Examples + + iex> list_survey_comments() + [%Comment{}, ...] + + """ + def list_survey_comments do + Repo.all(Comment) + end + + @doc """ + Gets a single comment. + + Raises `Ecto.NoResultsError` if the Comment does not exist. + + ## Examples + + iex> get_comment!(123) + %Comment{} + + iex> get_comment!(456) + ** (Ecto.NoResultsError) + + """ + def get_comment!(id), do: Repo.get!(Comment, id) + + @doc """ + Creates a comment. + + ## Examples + + iex> create_comment(%{field: value}) + {:ok, %Comment{}} + + iex> create_comment(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_comment(attrs \\ %{}) do + %Comment{} + |> Comment.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a comment. + + ## Examples + + iex> update_comment(comment, %{field: new_value}) + {:ok, %Comment{}} + + iex> update_comment(comment, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_comment(%Comment{} = comment, attrs) do + comment + |> Comment.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a comment. + + ## Examples + + iex> delete_comment(comment) + {:ok, %Comment{}} + + iex> delete_comment(comment) + {:error, %Ecto.Changeset{}} + + """ + def delete_comment(%Comment{} = comment) do + Repo.delete(comment) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking comment changes. + + ## Examples + + iex> change_comment(comment) + %Ecto.Changeset{data: %Comment{}} + + """ + def change_comment(%Comment{} = comment, attrs \\ %{}) do + Comment.changeset(comment, attrs) + end + + def list_poll_comments(%Poll{} = poll) do + query = from(Comment, where: [poll_id: ^poll.id]) + Repo.all(query) + end + alias Diskuy.Survey.Choice @doc """ @@ -113,9 +214,8 @@ defmodule Diskuy.Survey do [%Choice{}, ...] """ - def list_choices(poll) do - from(c in Choice, where: [poll_id: ^poll.id], order_by: [asc: :id]) - |> Repo.all() + def list_choices do + Repo.all(Choice) end @doc """ @@ -132,7 +232,7 @@ defmodule Diskuy.Survey do ** (Ecto.NoResultsError) """ - def get_choice!(poll, id), do: Repo.get_by!(Choice, poll_id: poll.id, id: id) + def get_choice!(id), do: Repo.get!(Choice, id) @doc """ Creates a choice. @@ -146,9 +246,8 @@ defmodule Diskuy.Survey do {:error, %Ecto.Changeset{}} """ - def create_choice(poll, attrs \\ %{}) do + def create_choice(attrs \\ %{}) do %Choice{} - |> Ecto.build_assoc(:choices) |> Choice.changeset(attrs) |> Repo.insert() end @@ -200,6 +299,11 @@ defmodule Diskuy.Survey do Choice.changeset(choice, attrs) end + def list_poll_choices(%Poll{} = poll) do + query = from(Choice, where: [poll_id: ^poll.id]) + Repo.all(query) + end + alias Diskuy.Survey.Vote @doc """ @@ -211,9 +315,8 @@ defmodule Diskuy.Survey do [%Vote{}, ...] """ - def list_votes(choice) do - from(v in Votes, where: [choice_id: ^choice.id], order_by: [asc: :id]) - |> Repo.all() + def list_votes do + Repo.all(Vote) end @doc """ @@ -230,7 +333,7 @@ defmodule Diskuy.Survey do ** (Ecto.NoResultsError) """ - def get_vote!(choice, id), do: Repo.get_by!(Vote, choice_id: choice.id, id: id) + def get_vote!(id), do: Repo.get!(Vote, id) @doc """ Creates a vote. @@ -244,9 +347,8 @@ defmodule Diskuy.Survey do {:error, %Ecto.Changeset{}} """ - def create_vote(choice, attrs \\ %{}) do + def create_vote(attrs \\ %{}) do %Vote{} - |> Ecto.build_assoc(:votes) |> Vote.changeset(attrs) |> Repo.insert() end @@ -297,105 +399,4 @@ defmodule Diskuy.Survey do def change_vote(%Vote{} = vote, attrs \\ %{}) do Vote.changeset(vote, attrs) end - - alias Diskuy.Survey.Comment - - @doc """ - Returns the list of survey_comments. - - ## Examples - - iex> list_survey_comments() - [%Comment{}, ...] - - """ - def list_survey_comments do - Repo.all(Comment) - end - - @doc """ - Gets a single comment. - - Raises `Ecto.NoResultsError` if the Comment does not exist. - - ## Examples - - iex> get_comment!(123) - %Comment{} - - iex> get_comment!(456) - ** (Ecto.NoResultsError) - - """ - def get_comment!(id), do: Repo.get!(Comment, id) - - @doc """ - Creates a comment. - - ## Examples - - iex> create_comment(%{field: value}) - {:ok, %Comment{}} - - iex> create_comment(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_comment(attrs \\ %{}) do - %Comment{} - |> Comment.changeset(attrs) - |> Repo.insert() - end - - @doc """ - Updates a comment. - - ## Examples - - iex> update_comment(comment, %{field: new_value}) - {:ok, %Comment{}} - - iex> update_comment(comment, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_comment(%Comment{} = comment, attrs) do - comment - |> Comment.changeset(attrs) - |> Repo.update() - end - - @doc """ - Deletes a comment. - - ## Examples - - iex> delete_comment(comment) - {:ok, %Comment{}} - - iex> delete_comment(comment) - {:error, %Ecto.Changeset{}} - - """ - def delete_comment(%Comment{} = comment) do - Repo.delete(comment) - end - - @doc """ - Returns an `%Ecto.Changeset{}` for tracking comment changes. - - ## Examples - - iex> change_comment(comment) - %Ecto.Changeset{data: %Comment{}} - - """ - def change_comment(%Comment{} = comment, attrs \\ %{}) do - Comment.changeset(comment, attrs) - end - - def list_poll_comments(%Poll{} = poll) do - query = from(Comment, where: [poll_id: ^poll.id]) - Repo.all(query) - end end diff --git a/lib/diskuy/survey/choice.ex b/lib/diskuy/survey/choice.ex index 374e9df..ef1a2b6 100644 --- a/lib/diskuy/survey/choice.ex +++ b/lib/diskuy/survey/choice.ex @@ -3,9 +3,8 @@ defmodule Diskuy.Survey.Choice do import Ecto.Changeset schema "choices" do - field :name, :string - belongs_to :poll, Diskuy.Survey.Poll - has_many :votes, Diskuy.Survey.Vote + field :choice, :string + field :poll_id, :id timestamps() end @@ -13,7 +12,7 @@ defmodule Diskuy.Survey.Choice do @doc false def changeset(choice, attrs) do choice - |> cast(attrs, [:name]) - |> validate_required([:name]) + |> cast(attrs, [:choice, :poll_id]) + |> validate_required([:choice, :poll_id]) end end diff --git a/lib/diskuy/survey/poll.ex b/lib/diskuy/survey/poll.ex index b25f86c..6dbbeb4 100644 --- a/lib/diskuy/survey/poll.ex +++ b/lib/diskuy/survey/poll.ex @@ -8,7 +8,6 @@ defmodule Diskuy.Survey.Poll do field :title, :string field :topic_id, :id field :user_id, :id - has_many :choices, Diskuy.Survey.Choice timestamps() end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index 23b344e..18a9ca9 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -4,7 +4,7 @@ defmodule Diskuy.Survey.Vote do schema "votes" do field :user_id, :id - belongs_to :choice, Diskuy.Survey.Choice + field :choice_id, :id timestamps() end @@ -12,7 +12,8 @@ defmodule Diskuy.Survey.Vote do @doc false def changeset(vote, attrs) do vote - |> cast(attrs, [:user_id]) - |> validate_required([:user_id]) + |> cast(attrs, []) + |> validate_required([]) + |> unique_constraint(:unique_user, name: :vote_unique_index) end end diff --git a/lib/diskuy_web/controllers/choice_controller.ex b/lib/diskuy_web/controllers/choice_controller.ex index 57922fd..3a3255b 100644 --- a/lib/diskuy_web/controllers/choice_controller.ex +++ b/lib/diskuy_web/controllers/choice_controller.ex @@ -1,26 +1,36 @@ defmodule DiskuyWeb.ChoiceController do use DiskuyWeb, :controller + require Logger alias Diskuy.Survey alias Diskuy.Survey.Choice action_fallback DiskuyWeb.FallbackController - def index(conn, _params) do - choices = Survey.list_choices() + def index(conn, %{"id_survey" => id_survey}) do + poll = Survey.get_poll!(id_survey) + choices = Survey.list_poll_choices(poll) render(conn, "index.json", choices: choices) end - def create(conn, %{"choice" => choice_params}) do + def create(conn, %{"choice" => choice_params, "id_survey" => id_survey}) do + choice_params = put_poll_id(%{"choice" => choice_params, "id_survey" => id_survey}) with {:ok, %Choice{} = choice} <- Survey.create_choice(choice_params) do + Logger.info("choice = #{inspect(choice)}") conn |> put_status(:created) - |> put_resp_header("location", Routes.choice_path(conn, :show, choice)) + |> put_resp_header("location", Routes.choice_path(conn, :show, id_survey, choice)) |> render("show.json", choice: choice) end end def show(conn, %{"id" => id}) do + choice = Survey.get_choice!(id) + Logger.info("choice = #{inspect(choice)}") + render(conn, "show.json", choice: choice) + end + + def alt_show(conn, %{"id" => id}) do choice = Survey.get_choice!(id) render(conn, "show.json", choice: choice) end @@ -40,4 +50,14 @@ defmodule DiskuyWeb.ChoiceController do send_resp(conn, :no_content, "") end end + + def list_all(conn, _params) do + choices = Survey.list_choices() + render(conn, "index.json", choices: choices) + end + + defp put_poll_id(%{"choice" => choice_params, "id_survey" => id_survey}) do + new_params = Map.put(choice_params, "poll_id", id_survey) + new_params + end end diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 97dbd0a..8d21ad2 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -41,9 +41,8 @@ defmodule DiskuyWeb.Router do options "/post/checklike/:id", PostLikeController, :options resources "/survey", PollController, except: [:new, :edit, :show, :index] - get "/survey/:id/comments", CommentController, :get_poll_comments - resources "/comment", CommentController, except: [:new, :edit, :show, :index] + resources "/survey/:id_survey/choice", ChoiceController, except: [:new, :edit, :show, :index] end scope "/api", DiskuyWeb do @@ -96,6 +95,12 @@ defmodule DiskuyWeb.Router do options "/comment", CommentController, :options options "/comment/:id", CommentController, :options + resources "/survey/:id_survey/choice", ChoiceController, except: [:new, :edit, :create, :update, :delete] + get "/survey/choice", ChoiceController, :list_all + get "/survey/choice/:id", ChoiceController, :alt_show + options "/choice", ChoiceController, :options + options "/choice/:id", ChoiceController, :options + end scope "/api/auth", DiskuyWeb do diff --git a/lib/diskuy_web/views/choice_view.ex b/lib/diskuy_web/views/choice_view.ex index 09f8a47..012150b 100644 --- a/lib/diskuy_web/views/choice_view.ex +++ b/lib/diskuy_web/views/choice_view.ex @@ -12,6 +12,8 @@ defmodule DiskuyWeb.ChoiceView do def render("choice.json", %{choice: choice}) do %{id: choice.id, - name: choice.name} + choice: choice.choice, + poll_id: choice.poll_id + } end end diff --git a/lib/diskuy_web/views/comment_view.ex b/lib/diskuy_web/views/comment_view.ex index 7ef8866..d154d2e 100644 --- a/lib/diskuy_web/views/comment_view.ex +++ b/lib/diskuy_web/views/comment_view.ex @@ -1,11 +1,9 @@ defmodule DiskuyWeb.CommentView do - require Logger use DiskuyWeb, :view alias DiskuyWeb.CommentView alias Diskuy.Account def render("index.json", %{survey_comments: survey_comments}) do - Logger.debug "query: #{inspect(survey_comments)}" %{data: render_many(survey_comments, CommentView, "comment.json")} end diff --git a/lib/diskuy_web/views/poll_view.ex b/lib/diskuy_web/views/poll_view.ex index 5aaf560..9182255 100644 --- a/lib/diskuy_web/views/poll_view.ex +++ b/lib/diskuy_web/views/poll_view.ex @@ -1,6 +1,8 @@ defmodule DiskuyWeb.PollView do use DiskuyWeb, :view alias DiskuyWeb.PollView + alias DiskuyWeb.CommentView + alias Diskuy.Survey alias Diskuy.Account def render("index.json", %{polls: polls}) do @@ -12,6 +14,8 @@ defmodule DiskuyWeb.PollView do end def render("poll.json", %{poll: poll}) do + comments = Survey.list_poll_comments(poll) + comment_view = render_many(comments, CommentView, "comment.json") user = Account.get_user!(poll.user_id) %{id: poll.id, points: poll.points, @@ -19,7 +23,8 @@ defmodule DiskuyWeb.PollView do end_time: poll.end_time, topic_id: poll.topic_id, user_id: poll.user_id, - username: user.username + username: user.username, + comments: comment_view } end end diff --git a/priv/repo/migrations/20211211065254_create_choices.exs b/priv/repo/migrations/20211229120501_create_choices.exs similarity index 55% rename from priv/repo/migrations/20211211065254_create_choices.exs rename to priv/repo/migrations/20211229120501_create_choices.exs index 6f2660e..b401210 100644 --- a/priv/repo/migrations/20211211065254_create_choices.exs +++ b/priv/repo/migrations/20211229120501_create_choices.exs @@ -3,12 +3,12 @@ defmodule Diskuy.Repo.Migrations.CreateChoices do def change do create table(:choices) do - add :name, :string - add :poll, references(:polls, on_delete: :nothing) + add :choice, :string + add :poll_id, references(:polls, on_delete: :nothing) timestamps() end - create index(:choices, [:poll]) + create index(:choices, [:poll_id]) end end diff --git a/priv/repo/migrations/20211211071242_create_votes.exs b/priv/repo/migrations/20211229121200_create_votes.exs similarity index 52% rename from priv/repo/migrations/20211211071242_create_votes.exs rename to priv/repo/migrations/20211229121200_create_votes.exs index a957f54..78e5f1e 100644 --- a/priv/repo/migrations/20211211071242_create_votes.exs +++ b/priv/repo/migrations/20211229121200_create_votes.exs @@ -3,14 +3,14 @@ defmodule Diskuy.Repo.Migrations.CreateVotes do def change do create table(:votes) do - add :user_id, references(:users, on_delete: :delete_all) - add :choice_id, references(:choices, on_delete: :delete_all) + add :user_id, references(:users, on_delete: :nothing) + add :choice_id, references(:choices, on_delete: :nothing) timestamps() end create index(:votes, [:user_id]) create index(:votes, [:choice_id]) - create unique_index(:votes, [:user_id, :user_id, :choice_id]) + create unique_index(:votes, [:user_id, :choice_id], name: :vote_unique_index) end end diff --git a/test/diskuy/survey_test.exs b/test/diskuy/survey_test.exs index 985196a..ea76d6a 100644 --- a/test/diskuy/survey_test.exs +++ b/test/diskuy/survey_test.exs @@ -255,4 +255,120 @@ defmodule Diskuy.SurveyTest do assert %Ecto.Changeset{} = Survey.change_comment(comment) end end + + describe "choices" do + alias Diskuy.Survey.Choice + + @valid_attrs %{choice: "some choice"} + @update_attrs %{choice: "some updated choice"} + @invalid_attrs %{choice: nil} + + def choice_fixture(attrs \\ %{}) do + {:ok, choice} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_choice() + + choice + end + + test "list_choices/0 returns all choices" do + choice = choice_fixture() + assert Survey.list_choices() == [choice] + end + + test "get_choice!/1 returns the choice with given id" do + choice = choice_fixture() + assert Survey.get_choice!(choice.id) == choice + end + + test "create_choice/1 with valid data creates a choice" do + assert {:ok, %Choice{} = choice} = Survey.create_choice(@valid_attrs) + assert choice.choice == "some choice" + end + + test "create_choice/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Survey.create_choice(@invalid_attrs) + end + + test "update_choice/2 with valid data updates the choice" do + choice = choice_fixture() + assert {:ok, %Choice{} = choice} = Survey.update_choice(choice, @update_attrs) + assert choice.choice == "some updated choice" + end + + test "update_choice/2 with invalid data returns error changeset" do + choice = choice_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_choice(choice, @invalid_attrs) + assert choice == Survey.get_choice!(choice.id) + end + + test "delete_choice/1 deletes the choice" do + choice = choice_fixture() + assert {:ok, %Choice{}} = Survey.delete_choice(choice) + assert_raise Ecto.NoResultsError, fn -> Survey.get_choice!(choice.id) end + end + + test "change_choice/1 returns a choice changeset" do + choice = choice_fixture() + assert %Ecto.Changeset{} = Survey.change_choice(choice) + end + end + + describe "votes" do + alias Diskuy.Survey.Vote + + @valid_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + def vote_fixture(attrs \\ %{}) do + {:ok, vote} = + attrs + |> Enum.into(@valid_attrs) + |> Survey.create_vote() + + vote + end + + test "list_votes/0 returns all votes" do + vote = vote_fixture() + assert Survey.list_votes() == [vote] + end + + test "get_vote!/1 returns the vote with given id" do + vote = vote_fixture() + assert Survey.get_vote!(vote.id) == vote + end + + test "create_vote/1 with valid data creates a vote" do + assert {:ok, %Vote{} = vote} = Survey.create_vote(@valid_attrs) + end + + test "create_vote/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Survey.create_vote(@invalid_attrs) + end + + test "update_vote/2 with valid data updates the vote" do + vote = vote_fixture() + assert {:ok, %Vote{} = vote} = Survey.update_vote(vote, @update_attrs) + end + + test "update_vote/2 with invalid data returns error changeset" do + vote = vote_fixture() + assert {:error, %Ecto.Changeset{}} = Survey.update_vote(vote, @invalid_attrs) + assert vote == Survey.get_vote!(vote.id) + end + + test "delete_vote/1 deletes the vote" do + vote = vote_fixture() + assert {:ok, %Vote{}} = Survey.delete_vote(vote) + assert_raise Ecto.NoResultsError, fn -> Survey.get_vote!(vote.id) end + end + + test "change_vote/1 returns a vote changeset" do + vote = vote_fixture() + assert %Ecto.Changeset{} = Survey.change_vote(vote) + end + end end diff --git a/test/diskuy_web/controllers/choice_controller_test.exs b/test/diskuy_web/controllers/choice_controller_test.exs index e6dd8b9..5813871 100644 --- a/test/diskuy_web/controllers/choice_controller_test.exs +++ b/test/diskuy_web/controllers/choice_controller_test.exs @@ -5,12 +5,12 @@ defmodule DiskuyWeb.ChoiceControllerTest do alias Diskuy.Survey.Choice @create_attrs %{ - name: "some name" + choice: "some choice" } @update_attrs %{ - name: "some updated name" + choice: "some updated choice" } - @invalid_attrs %{name: nil} + @invalid_attrs %{choice: nil} def fixture(:choice) do {:ok, choice} = Survey.create_choice(@create_attrs) @@ -37,7 +37,7 @@ defmodule DiskuyWeb.ChoiceControllerTest do assert %{ "id" => id, - "name" => "some name" + "choice" => "some choice" } = json_response(conn, 200)["data"] end @@ -58,7 +58,7 @@ defmodule DiskuyWeb.ChoiceControllerTest do assert %{ "id" => id, - "name" => "some updated name" + "choice" => "some updated choice" } = json_response(conn, 200)["data"] end -- GitLab From 26eb4153a283d4d6d061b5c2e29849758442cb27 Mon Sep 17 00:00:00 2001 From: azhar81 Date: Thu, 30 Dec 2021 20:41:04 +0700 Subject: [PATCH 21/23] feat: vote API --- lib/diskuy/survey.ex | 9 +++++++++ lib/diskuy/survey/vote.ex | 4 ++-- lib/diskuy_web/controllers/vote_controller.ex | 19 +++++++++---------- lib/diskuy_web/router.ex | 4 ++++ lib/diskuy_web/views/choice_view.ex | 5 ++++- lib/diskuy_web/views/poll_view.ex | 6 +++++- lib/diskuy_web/views/vote_view.ex | 2 +- .../20211229121200_create_votes.exs | 4 ++-- 8 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/diskuy/survey.ex b/lib/diskuy/survey.ex index 87f513b..7f32cad 100644 --- a/lib/diskuy/survey.ex +++ b/lib/diskuy/survey.ex @@ -399,4 +399,13 @@ defmodule Diskuy.Survey do def change_vote(%Vote{} = vote, attrs \\ %{}) do Vote.changeset(vote, attrs) end + + def get_vote_by_user_and_choice(user_id, choice_id) do + Repo.get_by(Vote, [user_id: user_id, choice_id: choice_id]) + end + + def count_choice_votes(%Choice{} = choice) do + query = from(Vote, where: [choice_id: ^choice.id]) + Repo.aggregate(query, :count, :id) + end end diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index 18a9ca9..ecdaba6 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -12,8 +12,8 @@ defmodule Diskuy.Survey.Vote do @doc false def changeset(vote, attrs) do vote - |> cast(attrs, []) - |> validate_required([]) + |> cast(attrs, [:user_id,:choice_id]) + |> validate_required([:user_id,:choice_id]) |> unique_constraint(:unique_user, name: :vote_unique_index) end end diff --git a/lib/diskuy_web/controllers/vote_controller.ex b/lib/diskuy_web/controllers/vote_controller.ex index bc5235e..657fdc5 100644 --- a/lib/diskuy_web/controllers/vote_controller.ex +++ b/lib/diskuy_web/controllers/vote_controller.ex @@ -1,5 +1,6 @@ defmodule DiskuyWeb.VoteController do use DiskuyWeb, :controller + require Logger alias Diskuy.Survey alias Diskuy.Survey.Vote @@ -11,20 +12,17 @@ defmodule DiskuyWeb.VoteController do render(conn, "index.json", votes: votes) end - def create(conn, %{"vote" => vote_params}) do - with {:ok, %Vote{} = vote} <- Survey.create_vote(vote_params) do + def create(conn, %{"id_choice" => id_choice}) do + current_user = Guardian.Plug.current_resource(conn) + Logger.info("user: #{inspect(current_user)}") + params = %{"user_id" => current_user.id, "choice_id" => id_choice} + with {:ok, %Vote{} = vote} <- Survey.create_vote(params) do conn |> put_status(:created) - |> put_resp_header("location", Routes.vote_path(conn, :show, vote)) |> render("show.json", vote: vote) end end - def show(conn, %{"id" => id}) do - vote = Survey.get_vote!(id) - render(conn, "show.json", vote: vote) - end - def update(conn, %{"id" => id, "vote" => vote_params}) do vote = Survey.get_vote!(id) @@ -33,8 +31,9 @@ defmodule DiskuyWeb.VoteController do end end - def delete(conn, %{"id" => id}) do - vote = Survey.get_vote!(id) + def delete(conn, %{"id_choice" => id_choice}) do + current_user = Guardian.Plug.current_resource(conn) + vote = Survey.get_vote_by_user_and_choice(current_user.id, id_choice) with {:ok, %Vote{}} <- Survey.delete_vote(vote) do send_resp(conn, :no_content, "") diff --git a/lib/diskuy_web/router.ex b/lib/diskuy_web/router.ex index 8d21ad2..904a8ba 100644 --- a/lib/diskuy_web/router.ex +++ b/lib/diskuy_web/router.ex @@ -43,6 +43,8 @@ defmodule DiskuyWeb.Router do resources "/survey", PollController, except: [:new, :edit, :show, :index] resources "/comment", CommentController, except: [:new, :edit, :show, :index] resources "/survey/:id_survey/choice", ChoiceController, except: [:new, :edit, :show, :index] + post "/survey/choice/:id_choice/vote", VoteController, :create + post "/survey/choice/:id_choice/unvote", VoteController, :delete end scope "/api", DiskuyWeb do @@ -101,6 +103,8 @@ defmodule DiskuyWeb.Router do options "/choice", ChoiceController, :options options "/choice/:id", ChoiceController, :options + get "survey/choice/:id/votes", ChoiceController, :vote_count + end scope "/api/auth", DiskuyWeb do diff --git a/lib/diskuy_web/views/choice_view.ex b/lib/diskuy_web/views/choice_view.ex index 012150b..8844614 100644 --- a/lib/diskuy_web/views/choice_view.ex +++ b/lib/diskuy_web/views/choice_view.ex @@ -1,6 +1,7 @@ defmodule DiskuyWeb.ChoiceView do use DiskuyWeb, :view alias DiskuyWeb.ChoiceView + alias Diskuy.Survey def render("index.json", %{choices: choices}) do %{data: render_many(choices, ChoiceView, "choice.json")} @@ -11,9 +12,11 @@ defmodule DiskuyWeb.ChoiceView do end def render("choice.json", %{choice: choice}) do + vote_count = Survey.count_choice_votes(choice) %{id: choice.id, choice: choice.choice, - poll_id: choice.poll_id + poll_id: choice.poll_id, + vote_count: vote_count } end end diff --git a/lib/diskuy_web/views/poll_view.ex b/lib/diskuy_web/views/poll_view.ex index 9182255..c0c859a 100644 --- a/lib/diskuy_web/views/poll_view.ex +++ b/lib/diskuy_web/views/poll_view.ex @@ -2,6 +2,7 @@ defmodule DiskuyWeb.PollView do use DiskuyWeb, :view alias DiskuyWeb.PollView alias DiskuyWeb.CommentView + alias DiskuyWeb.ChoiceView alias Diskuy.Survey alias Diskuy.Account @@ -16,6 +17,8 @@ defmodule DiskuyWeb.PollView do def render("poll.json", %{poll: poll}) do comments = Survey.list_poll_comments(poll) comment_view = render_many(comments, CommentView, "comment.json") + choices = Survey.list_poll_choices(poll) + choice_view = render_many(choices, ChoiceView, "choice.json") user = Account.get_user!(poll.user_id) %{id: poll.id, points: poll.points, @@ -24,7 +27,8 @@ defmodule DiskuyWeb.PollView do topic_id: poll.topic_id, user_id: poll.user_id, username: user.username, - comments: comment_view + comments: comment_view, + choices: choice_view } end end diff --git a/lib/diskuy_web/views/vote_view.ex b/lib/diskuy_web/views/vote_view.ex index 9acf185..d0d818d 100644 --- a/lib/diskuy_web/views/vote_view.ex +++ b/lib/diskuy_web/views/vote_view.ex @@ -11,6 +11,6 @@ defmodule DiskuyWeb.VoteView do end def render("vote.json", %{vote: vote}) do - %{id: vote.id} + %{user_id: vote.user_id} end end diff --git a/priv/repo/migrations/20211229121200_create_votes.exs b/priv/repo/migrations/20211229121200_create_votes.exs index 78e5f1e..5c0ce4c 100644 --- a/priv/repo/migrations/20211229121200_create_votes.exs +++ b/priv/repo/migrations/20211229121200_create_votes.exs @@ -3,8 +3,8 @@ defmodule Diskuy.Repo.Migrations.CreateVotes do def change do create table(:votes) do - add :user_id, references(:users, on_delete: :nothing) - add :choice_id, references(:choices, on_delete: :nothing) + add :user_id, references(:users, on_delete: :delete_all) + add :choice_id, references(:choices, on_delete: :delete_all) timestamps() end -- GitLab From bf02c2afb5ac64cb7b229834a1ee65b14e30416c Mon Sep 17 00:00:00 2001 From: azhar81 Date: Thu, 30 Dec 2021 21:00:43 +0700 Subject: [PATCH 22/23] fix: vote tidak dapat dillakukan ke dua pilihan berbeda --- lib/diskuy/survey/vote.ex | 6 ++++-- lib/diskuy_web/controllers/vote_controller.ex | 4 ++-- .../migrations/20211211075121_create_survey_comments.exs | 4 ++-- priv/repo/migrations/20211229120501_create_choices.exs | 2 +- priv/repo/migrations/20211229121200_create_votes.exs | 2 ++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/diskuy/survey/vote.ex b/lib/diskuy/survey/vote.ex index ecdaba6..b4a2188 100644 --- a/lib/diskuy/survey/vote.ex +++ b/lib/diskuy/survey/vote.ex @@ -5,6 +5,7 @@ defmodule Diskuy.Survey.Vote do schema "votes" do field :user_id, :id field :choice_id, :id + field :poll_id, :id timestamps() end @@ -12,8 +13,9 @@ defmodule Diskuy.Survey.Vote do @doc false def changeset(vote, attrs) do vote - |> cast(attrs, [:user_id,:choice_id]) - |> validate_required([:user_id,:choice_id]) + |> cast(attrs, [:user_id,:choice_id, :poll_id]) + |> validate_required([:user_id,:choice_id, :poll_id]) |> unique_constraint(:unique_user, name: :vote_unique_index) + |> unique_constraint(:unique_choice, name: :vote_unique_choice) end end diff --git a/lib/diskuy_web/controllers/vote_controller.ex b/lib/diskuy_web/controllers/vote_controller.ex index 657fdc5..a034b30 100644 --- a/lib/diskuy_web/controllers/vote_controller.ex +++ b/lib/diskuy_web/controllers/vote_controller.ex @@ -13,9 +13,9 @@ defmodule DiskuyWeb.VoteController do end def create(conn, %{"id_choice" => id_choice}) do + choice = Survey.get_choice!(id_choice) current_user = Guardian.Plug.current_resource(conn) - Logger.info("user: #{inspect(current_user)}") - params = %{"user_id" => current_user.id, "choice_id" => id_choice} + params = %{"user_id" => current_user.id, "choice_id" => id_choice, "poll_id" => choice.poll_id} with {:ok, %Vote{} = vote} <- Survey.create_vote(params) do conn |> put_status(:created) diff --git a/priv/repo/migrations/20211211075121_create_survey_comments.exs b/priv/repo/migrations/20211211075121_create_survey_comments.exs index 986ae04..05ee3b0 100644 --- a/priv/repo/migrations/20211211075121_create_survey_comments.exs +++ b/priv/repo/migrations/20211211075121_create_survey_comments.exs @@ -4,8 +4,8 @@ defmodule Diskuy.Repo.Migrations.CreateSurveyComments do def change do create table(:survey_comments) do add :comment, :text - add :user_id, references(:users, on_delete: :nothing) - add :poll_id, references(:polls, on_delete: :nothing) + add :user_id, references(:users, on_delete: :delete_all) + add :poll_id, references(:polls, on_delete: :delete_all) timestamps() end diff --git a/priv/repo/migrations/20211229120501_create_choices.exs b/priv/repo/migrations/20211229120501_create_choices.exs index b401210..5cad5f5 100644 --- a/priv/repo/migrations/20211229120501_create_choices.exs +++ b/priv/repo/migrations/20211229120501_create_choices.exs @@ -4,7 +4,7 @@ defmodule Diskuy.Repo.Migrations.CreateChoices do def change do create table(:choices) do add :choice, :string - add :poll_id, references(:polls, on_delete: :nothing) + add :poll_id, references(:polls, on_delete: :delete_all) timestamps() end diff --git a/priv/repo/migrations/20211229121200_create_votes.exs b/priv/repo/migrations/20211229121200_create_votes.exs index 5c0ce4c..ce31b2f 100644 --- a/priv/repo/migrations/20211229121200_create_votes.exs +++ b/priv/repo/migrations/20211229121200_create_votes.exs @@ -5,6 +5,7 @@ defmodule Diskuy.Repo.Migrations.CreateVotes do create table(:votes) do add :user_id, references(:users, on_delete: :delete_all) add :choice_id, references(:choices, on_delete: :delete_all) + add :poll_id, references(:polls, on_delete: :delete_all) timestamps() end @@ -12,5 +13,6 @@ defmodule Diskuy.Repo.Migrations.CreateVotes do create index(:votes, [:user_id]) create index(:votes, [:choice_id]) create unique_index(:votes, [:user_id, :choice_id], name: :vote_unique_index) + create unique_index(:votes, [:user_id, :poll_id], name: :vote_unique_choice) end end -- GitLab From c361e23d78e015115ebc672f2956958459f90790 Mon Sep 17 00:00:00 2001 From: azhar81 Date: Thu, 30 Dec 2021 21:02:29 +0700 Subject: [PATCH 23/23] feat: comment return timestamp --- lib/diskuy_web/views/comment_view.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/diskuy_web/views/comment_view.ex b/lib/diskuy_web/views/comment_view.ex index d154d2e..88599ff 100644 --- a/lib/diskuy_web/views/comment_view.ex +++ b/lib/diskuy_web/views/comment_view.ex @@ -17,7 +17,8 @@ defmodule DiskuyWeb.CommentView do user_id: comment.user_id, poll_id: comment.poll_id, username: user.username, - comment: comment.comment + comment: comment.comment, + timestamp: comment.inserted_at } end end -- GitLab