Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- Added specifications #5

Merged
merged 1 commit into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions lib/rent_cars/specifications.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
defmodule RentCars.Specifications do
@moduledoc """
The Specifications context.
"""

import Ecto.Query, warn: false
alias RentCars.Repo

alias RentCars.Specifications.Specification

@doc """
Returns the list of specifications.

## Examples

iex> list_specifications()
[%Specification{}, ...]

"""
def list_specifications do
Repo.all(Specification)
end

@doc """
Gets a single specification.

Raises `Ecto.NoResultsError` if the Specification does not exist.

## Examples

iex> get_specification!(123)
%Specification{}

iex> get_specification!(456)
** (Ecto.NoResultsError)

"""
def get_specification!(id), do: Repo.get!(Specification, id)

@doc """
Creates a specification.

## Examples

iex> create_specification(%{field: value})
{:ok, %Specification{}}

iex> create_specification(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_specification(attrs \\ %{}) do
%Specification{}
|> Specification.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a specification.

## Examples

iex> update_specification(specification, %{field: new_value})
{:ok, %Specification{}}

iex> update_specification(specification, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_specification(%Specification{} = specification, attrs) do
specification
|> Specification.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a specification.

## Examples

iex> delete_specification(specification)
{:ok, %Specification{}}

iex> delete_specification(specification)
{:error, %Ecto.Changeset{}}

"""
def delete_specification(%Specification{} = specification) do
Repo.delete(specification)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking specification changes.

## Examples

iex> change_specification(specification)
%Ecto.Changeset{data: %Specification{}}

"""
def change_specification(%Specification{} = specification, attrs \\ %{}) do
Specification.changeset(specification, attrs)
end
end
21 changes: 21 additions & 0 deletions lib/rent_cars/specifications/specification.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule RentCars.Specifications.Specification do
use Ecto.Schema
import Ecto.Changeset

@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "specifications" do
field :name, :string
field :description, :string

timestamps(type: :utc_datetime)
end

@doc false
def changeset(specification, attrs) do
specification
|> cast(attrs, [:name, :description])
|> validate_required([:name, :description])
|> unique_constraint(:name)
end
end
3 changes: 2 additions & 1 deletion lib/rent_cars_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule RentCarsWeb.CoreComponents do

alias Phoenix.LiveView.JS
import RentCarsWeb.Gettext
alias Phoenix.HTML.Form

@doc """
Renders a modal.
Expand Down Expand Up @@ -303,7 +304,7 @@ defmodule RentCarsWeb.CoreComponents do
def input(%{type: "checkbox"} = assigns) do
assigns =
assign_new(assigns, :checked, fn ->
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
Form.normalize_value("checkbox", assigns[:value])
end)

~H"""
Expand Down
45 changes: 45 additions & 0 deletions lib/rent_cars_web/controllers/api/specification_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule RentCarsWeb.Api.SpecificationController do
use RentCarsWeb, :controller

alias RentCars.Specifications
alias RentCars.Specifications.Specification

action_fallback RentCarsWeb.FallbackController

def index(conn, _params) do
specifications = Specifications.list_specifications()
render(conn, :index, specifications: specifications)
end

def create(conn, %{"specification" => specification_params}) do
with {:ok, %Specification{} = specification} <-
Specifications.create_specification(specification_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/api/specifications/#{specification}")

Check warning on line 19 in lib/rent_cars_web/controllers/api/specification_controller.ex

View workflow job for this annotation

GitHub Actions / check_security (1.14, 26)

no route path for RentCarsWeb.Router matches "/api/api/specifications/#{specification}"

Check warning on line 19 in lib/rent_cars_web/controllers/api/specification_controller.ex

View workflow job for this annotation

GitHub Actions / check_security (1.14, 26)

no route path for RentCarsWeb.Router matches "/api/api/specifications/#{specification}"

Check warning on line 19 in lib/rent_cars_web/controllers/api/specification_controller.ex

View workflow job for this annotation

GitHub Actions / check_security (1.14, 26)

no route path for RentCarsWeb.Router matches "/api/api/specifications/#{specification}"
|> render(:show, specification: specification)
end
end

def show(conn, %{"id" => id}) do
specification = Specifications.get_specification!(id)
render(conn, :show, specification: specification)
end

def update(conn, %{"id" => id, "specification" => specification_params}) do
specification = Specifications.get_specification!(id)

with {:ok, %Specification{} = specification} <-
Specifications.update_specification(specification, specification_params) do
render(conn, :show, specification: specification)
end
end

def delete(conn, %{"id" => id}) do
specification = Specifications.get_specification!(id)

with {:ok, %Specification{}} <- Specifications.delete_specification(specification) do
send_resp(conn, :no_content, "")
end
end
end
25 changes: 25 additions & 0 deletions lib/rent_cars_web/controllers/api/specification_json.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule RentCarsWeb.Api.SpecificationJSON do
alias RentCars.Specifications.Specification

@doc """
Renders a list of specifications.
"""
def index(%{specifications: specifications}) do
%{data: for(specification <- specifications, do: data(specification))}
end

@doc """
Renders a single specification.
"""
def show(%{specification: specification}) do
%{data: data(specification)}
end

defp data(%Specification{} = specification) do
%{
id: specification.id,
name: specification.name,
description: specification.description
}
end
end
24 changes: 24 additions & 0 deletions lib/rent_cars_web/controllers/fallback_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule RentCarsWeb.FallbackController do
@moduledoc """
Translates controller action results into valid `Plug.Conn` responses.

See `Phoenix.Controller.action_fallback/1` for more details.
"""
use RentCarsWeb, :controller

# This clause handles errors returned by Ecto's insert/update/delete.
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
conn
|> put_status(:unprocessable_entity)
|> put_view(json: RentCarsWeb.ChangesetJSON)
|> render(:error, changeset: changeset)
end

# This clause is an example of how to handle resources that cannot be found.
def call(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> put_view(html: RentCarsWeb.ErrorHTML, json: RentCarsWeb.ErrorJSON)
|> render(:"404")
end
end
2 changes: 2 additions & 0 deletions lib/rent_cars_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ defmodule RentCarsWeb.Router do
get "/categories/:id", CategoryController, :show
put "/categories/:id", CategoryController, :update
delete "/categories/:id", CategoryController, :delete

resources "/specifications", SpecificationController
end

# Enable LiveDashboard and Swoosh mailbox preview in development
Expand Down
15 changes: 15 additions & 0 deletions priv/repo/migrations/20240102102111_create_specifications.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule RentCars.Repo.Migrations.CreateSpecifications do
use Ecto.Migration

def change do
create table(:specifications, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :description, :text

timestamps(type: :utc_datetime)
end

create unique_index(:specifications, [:name])
end
end
71 changes: 71 additions & 0 deletions test/rent_cars/specifications_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
defmodule RentCars.SpecificationsTest do
use RentCars.DataCase

alias RentCars.Specifications

describe "specifications" do
alias RentCars.Specifications.Specification

import RentCars.SpecificationsFixtures

@invalid_attrs %{name: nil, description: nil}

test "list_specifications/0 returns all specifications" do
specification = specification_fixture()
assert Specifications.list_specifications() == [specification]
end

test "get_specification!/1 returns the specification with given id" do
specification = specification_fixture()
assert Specifications.get_specification!(specification.id) == specification
end

test "create_specification/1 with valid data creates a specification" do
valid_attrs = %{name: "some name", description: "some description"}

assert {:ok, %Specification{} = specification} =
Specifications.create_specification(valid_attrs)

assert specification.name == "some name"
assert specification.description == "some description"
end

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

test "update_specification/2 with valid data updates the specification" do
specification = specification_fixture()
update_attrs = %{name: "some updated name", description: "some updated description"}

assert {:ok, %Specification{} = specification} =
Specifications.update_specification(specification, update_attrs)

assert specification.name == "some updated name"
assert specification.description == "some updated description"
end

test "update_specification/2 with invalid data returns error changeset" do
specification = specification_fixture()

assert {:error, %Ecto.Changeset{}} =
Specifications.update_specification(specification, @invalid_attrs)

assert specification == Specifications.get_specification!(specification.id)
end

test "delete_specification/1 deletes the specification" do
specification = specification_fixture()
assert {:ok, %Specification{}} = Specifications.delete_specification(specification)

assert_raise Ecto.NoResultsError, fn ->
Specifications.get_specification!(specification.id)
end
end

test "change_specification/1 returns a specification changeset" do
specification = specification_fixture()
assert %Ecto.Changeset{} = Specifications.change_specification(specification)
end
end
end
Loading
Loading