Skip to content

Commit

Permalink
implement categories crud
Browse files Browse the repository at this point in the history
  • Loading branch information
ksevelyar committed Nov 3, 2023
1 parent 5de4328 commit 50814ee
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 25 deletions.
32 changes: 32 additions & 0 deletions lib/market/categories.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Market.Categories do
import Ecto.Query, warn: false
alias Market.Repo

alias Market.Categories.Category

def list_categories do
Repo.all(Category)
end

def get_category!(id), do: Repo.get!(Category, id)

def create_category(attrs \\ %{}) do
%Category{}
|> Category.changeset(attrs)
|> Repo.insert()
end

def update_category(%Category{} = category, attrs) do
category
|> Category.changeset(attrs)
|> Repo.update()
end

def delete_category(%Category{} = category) do
Repo.delete(category)
end

def change_category(%Category{} = category, attrs \\ %{}) do
Category.changeset(category, attrs)
end
end
18 changes: 18 additions & 0 deletions lib/market/categories/category.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Market.Categories.Category do
use Ecto.Schema
import Ecto.Changeset

schema "categories" do
field :name, :string

timestamps()
end

@doc false
def changeset(category, attrs) do
category
|> cast(attrs, [:name])
|> validate_required([:name])
|> unique_constraint(:name)
end
end
42 changes: 42 additions & 0 deletions lib/market_web/controllers/category_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule MarketWeb.CategoryController do
use MarketWeb, :controller

alias Market.Categories
alias Market.Categories.Category

action_fallback MarketWeb.FallbackController

def index(conn, _params) do
categories = Categories.list_categories()
render(conn, :index, categories: categories)
end

def create(conn, %{"category" => category_params}) do
with {:ok, %Category{} = category} <- Categories.create_category(category_params) do
conn
|> put_status(:created)
|> render(:show, category: category)
end
end

def show(conn, %{"id" => id}) do
category = Categories.get_category!(id)
render(conn, :show, category: category)
end

def update(conn, %{"id" => id, "category" => category_params}) do
category = Categories.get_category!(id)

with {:ok, %Category{} = category} <- Categories.update_category(category, category_params) do
render(conn, :show, category: category)
end
end

def delete(conn, %{"id" => id}) do
category = Categories.get_category!(id)

with {:ok, %Category{}} <- Categories.delete_category(category) do
send_resp(conn, :no_content, "")
end
end
end
18 changes: 18 additions & 0 deletions lib/market_web/controllers/category_json.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule MarketWeb.CategoryJSON do
alias Market.Categories.Category

def index(%{categories: categories}) do
%{data: for(category <- categories, do: data(category))}
end

def show(%{category: category}) do
%{data: data(category)}
end

defp data(%Category{} = category) do
%{
id: category.id,
name: category.name
}
end
end
23 changes: 0 additions & 23 deletions lib/market_web/controllers/vendor_category_controller.ex

This file was deleted.

12 changes: 10 additions & 2 deletions lib/market_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ defmodule MarketWeb.Router do
plug :accepts, ["json"]
end

pipeline :vendor_api do
plug :accepts, ["json"]
plug :fetch_session
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :fetch_current_vendor
end

scope "/", MarketWeb do
pipe_through :api

Expand All @@ -17,12 +25,12 @@ defmodule MarketWeb.Router do
end

scope "/", MarketWeb do
pipe_through [:api, :require_authenticated_vendor]
pipe_through [:vendor_api, :require_authenticated_vendor]

resources "/vendors/products", VendorProductController,
only: [:index, :show, :create, :delete, :update]

resources "/vendors/categories", VendorCategoryController,
resources "/categories", CategoryController,
only: [:index, :show, :create, :delete, :update]

resources "/vendors/orders", VendorOrderController, only: [:index, :show, :update]
Expand Down
13 changes: 13 additions & 0 deletions priv/repo/migrations/20231103201254_create_categories.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Market.Repo.Migrations.CreateCategories do
use Ecto.Migration

def change do
create table(:categories) do
add :name, :string

timestamps()
end

create unique_index(:categories, [:name])
end
end
59 changes: 59 additions & 0 deletions test/market/categories_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule Market.CategoriesTest do
use Market.DataCase

alias Market.Categories

describe "categories" do
alias Market.Categories.Category

import Market.CategoriesFixtures

@invalid_attrs %{name: nil}

test "list_categories/0 returns all categories" do
category = category_fixture()
assert Categories.list_categories() == [category]
end

test "get_category!/1 returns the category with given id" do
category = category_fixture()
assert Categories.get_category!(category.id) == category
end

test "create_category/1 with valid data creates a category" do
valid_attrs = %{name: "some name"}

assert {:ok, %Category{} = category} = Categories.create_category(valid_attrs)
assert category.name == "some name"
end

test "create_category/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Categories.create_category(@invalid_attrs)
end

test "update_category/2 with valid data updates the category" do
category = category_fixture()
update_attrs = %{name: "some updated name"}

assert {:ok, %Category{} = category} = Categories.update_category(category, update_attrs)
assert category.name == "some updated name"
end

test "update_category/2 with invalid data returns error changeset" do
category = category_fixture()
assert {:error, %Ecto.Changeset{}} = Categories.update_category(category, @invalid_attrs)
assert category == Categories.get_category!(category.id)
end

test "delete_category/1 deletes the category" do
category = category_fixture()
assert {:ok, %Category{}} = Categories.delete_category(category)
assert_raise Ecto.NoResultsError, fn -> Categories.get_category!(category.id) end
end

test "change_category/1 returns a category changeset" do
category = category_fixture()
assert %Ecto.Changeset{} = Categories.change_category(category)
end
end
end
88 changes: 88 additions & 0 deletions test/market_web/controllers/category_controller_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
defmodule MarketWeb.CategoryControllerTest do
use MarketWeb.ConnCase

import Market.CategoriesFixtures

alias Market.Categories.Category

@create_attrs %{
name: "some name"
}
@update_attrs %{
name: "some updated name"
}
@invalid_attrs %{name: nil}

setup :register_and_log_in_vendor
setup %{conn: conn} do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end

describe "index" do
test "lists all categories", %{conn: conn} do
conn = get(conn, ~p"/categories")
assert json_response(conn, 200)["data"] == []
end
end

describe "create category" do
test "renders category when data is valid", %{conn: conn} do
conn = post(conn, ~p"/categories", category: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"]

conn = get(conn, ~p"/categories/#{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, ~p"/categories", category: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end

describe "update category" do
setup [:create_category]

test "renders category when data is valid", %{
conn: conn,
category: %Category{id: id} = category
} do
conn = put(conn, ~p"/categories/#{category}", category: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"]

conn = get(conn, ~p"/categories/#{id}")

assert %{
"id" => ^id,
"name" => "some updated name"
} = json_response(conn, 200)["data"]
end

test "renders errors when data is invalid", %{conn: conn, category: category} do
conn = put(conn, ~p"/categories/#{category}", category: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end

describe "delete category" do
setup [:create_category]

test "deletes chosen category", %{conn: conn, category: category} do
conn = delete(conn, ~p"/categories/#{category}")
assert response(conn, 204)

assert_error_sent 404, fn ->
get(conn, ~p"/categories/#{category}")
end
end
end

defp create_category(_) do
category = category_fixture()
%{category: category}
end
end
25 changes: 25 additions & 0 deletions test/support/fixtures/categories_fixtures.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Market.CategoriesFixtures do
@moduledoc """
This module defines test helpers for creating
entities via the `Market.Categories` context.
"""

@doc """
Generate a unique category name.
"""
def unique_category_name, do: "some name#{System.unique_integer([:positive])}"

@doc """
Generate a category.
"""
def category_fixture(attrs \\ %{}) do
{:ok, category} =
attrs
|> Enum.into(%{
name: unique_category_name()
})
|> Market.Categories.create_category()

category
end
end

0 comments on commit 50814ee

Please sign in to comment.