add shops context, clothes and users-clothes
users-clothes is a many-to-many unique relationship
This commit is contained in:
		
							parent
							
								
									28823a6972
								
							
						
					
					
						commit
						4f8b87a2d9
					
				| @ -8,6 +8,7 @@ defmodule PokemonCouture.Accounts.User do | ||||
|     field :password, :string, virtual: true | ||||
|     field :hashed_password, :string | ||||
|     field :confirmed_at, :naive_datetime | ||||
|     many_to_many :clothes, PokemonCouture.Shops.Clothes, join_through: "ownerships", unique: :true | ||||
| 
 | ||||
|     timestamps() | ||||
|   end | ||||
|  | ||||
							
								
								
									
										104
									
								
								lib/pokemon_couture/shops.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								lib/pokemon_couture/shops.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| defmodule PokemonCouture.Shops do | ||||
|   @moduledoc """ | ||||
|   The Shops context. | ||||
|   """ | ||||
| 
 | ||||
|   import Ecto.Query, warn: false | ||||
|   alias PokemonCouture.Repo | ||||
| 
 | ||||
|   alias PokemonCouture.Shops.Clothes | ||||
| 
 | ||||
|   @doc """ | ||||
|   Returns the list of clothes. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> list_clothes() | ||||
|       [%Clothes{}, ...] | ||||
| 
 | ||||
|   """ | ||||
|   def list_clothes do | ||||
|     Repo.all(Clothes) | ||||
|   end | ||||
| 
 | ||||
|   @doc """ | ||||
|   Gets a single clothes. | ||||
| 
 | ||||
|   Raises `Ecto.NoResultsError` if the Clothes does not exist. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> get_clothes!(123) | ||||
|       %Clothes{} | ||||
| 
 | ||||
|       iex> get_clothes!(456) | ||||
|       ** (Ecto.NoResultsError) | ||||
| 
 | ||||
|   """ | ||||
|   def get_clothes!(id), do: Repo.get!(Clothes, id) | ||||
| 
 | ||||
|   @doc """ | ||||
|   Creates a clothes. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> create_clothes(%{field: value}) | ||||
|       {:ok, %Clothes{}} | ||||
| 
 | ||||
|       iex> create_clothes(%{field: bad_value}) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
| 
 | ||||
|   """ | ||||
|   def create_clothes(attrs \\ %{}) do | ||||
|     %Clothes{} | ||||
|     |> Clothes.changeset(attrs) | ||||
|     |> Repo.insert() | ||||
|   end | ||||
| 
 | ||||
|   @doc """ | ||||
|   Updates a clothes. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> update_clothes(clothes, %{field: new_value}) | ||||
|       {:ok, %Clothes{}} | ||||
| 
 | ||||
|       iex> update_clothes(clothes, %{field: bad_value}) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
| 
 | ||||
|   """ | ||||
|   def update_clothes(%Clothes{} = clothes, attrs) do | ||||
|     clothes | ||||
|     |> Clothes.changeset(attrs) | ||||
|     |> Repo.update() | ||||
|   end | ||||
| 
 | ||||
|   @doc """ | ||||
|   Deletes a clothes. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> delete_clothes(clothes) | ||||
|       {:ok, %Clothes{}} | ||||
| 
 | ||||
|       iex> delete_clothes(clothes) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
| 
 | ||||
|   """ | ||||
|   def delete_clothes(%Clothes{} = clothes) do | ||||
|     Repo.delete(clothes) | ||||
|   end | ||||
| 
 | ||||
|   @doc """ | ||||
|   Returns an `%Ecto.Changeset{}` for tracking clothes changes. | ||||
| 
 | ||||
|   ## Examples | ||||
| 
 | ||||
|       iex> change_clothes(clothes) | ||||
|       %Ecto.Changeset{data: %Clothes{}} | ||||
| 
 | ||||
|   """ | ||||
|   def change_clothes(%Clothes{} = clothes, attrs \\ %{}) do | ||||
|     Clothes.changeset(clothes, attrs) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										20
									
								
								lib/pokemon_couture/shops/clothes.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lib/pokemon_couture/shops/clothes.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| defmodule PokemonCouture.Shops.Clothes do | ||||
|   use Ecto.Schema | ||||
|   import Ecto.Changeset | ||||
| 
 | ||||
|   schema "clothes" do | ||||
|     field :game, :string | ||||
|     field :location, :string | ||||
|     field :name, :string | ||||
|     many_to_many :users, PokemonCouture.Accounts.User, join_through: "ownerships", unique: :true | ||||
| 
 | ||||
|     timestamps() | ||||
|   end | ||||
| 
 | ||||
|   @doc false | ||||
|   def changeset(clothes, attrs) do | ||||
|     clothes | ||||
|     |> cast(attrs, [:name, :location, :game]) | ||||
|     |> validate_required([:name, :location, :game]) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										62
									
								
								lib/pokemon_couture_web/controllers/clothes_controller.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								lib/pokemon_couture_web/controllers/clothes_controller.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| defmodule PokemonCoutureWeb.ClothesController do | ||||
|   use PokemonCoutureWeb, :controller | ||||
| 
 | ||||
|   alias PokemonCouture.Shops | ||||
|   alias PokemonCouture.Shops.Clothes | ||||
| 
 | ||||
|   def index(conn, _params) do | ||||
|     clothes = Shops.list_clothes() | ||||
|     render(conn, "index.html", clothes: clothes) | ||||
|   end | ||||
| 
 | ||||
|   def new(conn, _params) do | ||||
|     changeset = Shops.change_clothes(%Clothes{}) | ||||
|     render(conn, "new.html", changeset: changeset) | ||||
|   end | ||||
| 
 | ||||
|   def create(conn, %{"clothes" => clothes_params}) do | ||||
|     case Shops.create_clothes(clothes_params) do | ||||
|       {:ok, clothes} -> | ||||
|         conn | ||||
|         |> put_flash(:info, "Clothes created successfully.") | ||||
|         |> redirect(to: Routes.clothes_path(conn, :show, clothes)) | ||||
| 
 | ||||
|       {:error, %Ecto.Changeset{} = changeset} -> | ||||
|         render(conn, "new.html", changeset: changeset) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def show(conn, %{"id" => id}) do | ||||
|     clothes = Shops.get_clothes!(id) | ||||
|     render(conn, "show.html", clothes: clothes) | ||||
|   end | ||||
| 
 | ||||
|   def edit(conn, %{"id" => id}) do | ||||
|     clothes = Shops.get_clothes!(id) | ||||
|     changeset = Shops.change_clothes(clothes) | ||||
|     render(conn, "edit.html", clothes: clothes, changeset: changeset) | ||||
|   end | ||||
| 
 | ||||
|   def update(conn, %{"id" => id, "clothes" => clothes_params}) do | ||||
|     clothes = Shops.get_clothes!(id) | ||||
| 
 | ||||
|     case Shops.update_clothes(clothes, clothes_params) do | ||||
|       {:ok, clothes} -> | ||||
|         conn | ||||
|         |> put_flash(:info, "Clothes updated successfully.") | ||||
|         |> redirect(to: Routes.clothes_path(conn, :show, clothes)) | ||||
| 
 | ||||
|       {:error, %Ecto.Changeset{} = changeset} -> | ||||
|         render(conn, "edit.html", clothes: clothes, changeset: changeset) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def delete(conn, %{"id" => id}) do | ||||
|     clothes = Shops.get_clothes!(id) | ||||
|     {:ok, _clothes} = Shops.delete_clothes(clothes) | ||||
| 
 | ||||
|     conn | ||||
|     |> put_flash(:info, "Clothes deleted successfully.") | ||||
|     |> redirect(to: Routes.clothes_path(conn, :index)) | ||||
|   end | ||||
| end | ||||
| @ -20,6 +20,7 @@ defmodule PokemonCoutureWeb.Router do | ||||
|     pipe_through :browser | ||||
| 
 | ||||
|     get "/", PageController, :index | ||||
|     resources "/clothes", ClothesController | ||||
|   end | ||||
| 
 | ||||
|   # Other scopes may use custom stacks. | ||||
|  | ||||
							
								
								
									
										5
									
								
								lib/pokemon_couture_web/templates/clothes/edit.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/pokemon_couture_web/templates/clothes/edit.html.eex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <h1>Edit Clothes</h1> | ||||
| 
 | ||||
| <%= render "form.html", Map.put(assigns, :action, Routes.clothes_path(@conn, :update, @clothes)) %> | ||||
| 
 | ||||
| <span><%= link "Back", to: Routes.clothes_path(@conn, :index) %></span> | ||||
							
								
								
									
										23
									
								
								lib/pokemon_couture_web/templates/clothes/form.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/pokemon_couture_web/templates/clothes/form.html.eex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <%= form_for @changeset, @action, fn f -> %> | ||||
|   <%= if @changeset.action do %> | ||||
|     <div class="alert alert-danger"> | ||||
|       <p>Oops, something went wrong! Please check the errors below.</p> | ||||
|     </div> | ||||
|   <% end %> | ||||
| 
 | ||||
|   <%= label f, :name %> | ||||
|   <%= text_input f, :name %> | ||||
|   <%= error_tag f, :name %> | ||||
| 
 | ||||
|   <%= label f, :location %> | ||||
|   <%= text_input f, :location %> | ||||
|   <%= error_tag f, :location %> | ||||
| 
 | ||||
|   <%= label f, :game %> | ||||
|   <%= text_input f, :game %> | ||||
|   <%= error_tag f, :game %> | ||||
| 
 | ||||
|   <div> | ||||
|     <%= submit "Save" %> | ||||
|   </div> | ||||
| <% end %> | ||||
							
								
								
									
										30
									
								
								lib/pokemon_couture_web/templates/clothes/index.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								lib/pokemon_couture_web/templates/clothes/index.html.eex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| <h1>Listing Clothes</h1> | ||||
| 
 | ||||
| <table> | ||||
|   <thead> | ||||
|     <tr> | ||||
|       <th>Name</th> | ||||
|       <th>Location</th> | ||||
|       <th>Game</th> | ||||
| 
 | ||||
|       <th></th> | ||||
|     </tr> | ||||
|   </thead> | ||||
|   <tbody> | ||||
| <%= for clothes <- @clothes do %> | ||||
|     <tr> | ||||
|       <td><%= clothes.name %></td> | ||||
|       <td><%= clothes.location %></td> | ||||
|       <td><%= clothes.game %></td> | ||||
| 
 | ||||
|       <td> | ||||
|         <span><%= link "Show", to: Routes.clothes_path(@conn, :show, clothes) %></span> | ||||
|         <span><%= link "Edit", to: Routes.clothes_path(@conn, :edit, clothes) %></span> | ||||
|         <span><%= link "Delete", to: Routes.clothes_path(@conn, :delete, clothes), method: :delete, data: [confirm: "Are you sure?"] %></span> | ||||
|       </td> | ||||
|     </tr> | ||||
| <% end %> | ||||
|   </tbody> | ||||
| </table> | ||||
| 
 | ||||
| <span><%= link "New Clothes", to: Routes.clothes_path(@conn, :new) %></span> | ||||
							
								
								
									
										5
									
								
								lib/pokemon_couture_web/templates/clothes/new.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								lib/pokemon_couture_web/templates/clothes/new.html.eex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <h1>New Clothes</h1> | ||||
| 
 | ||||
| <%= render "form.html", Map.put(assigns, :action, Routes.clothes_path(@conn, :create)) %> | ||||
| 
 | ||||
| <span><%= link "Back", to: Routes.clothes_path(@conn, :index) %></span> | ||||
							
								
								
									
										23
									
								
								lib/pokemon_couture_web/templates/clothes/show.html.eex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/pokemon_couture_web/templates/clothes/show.html.eex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <h1>Show Clothes</h1> | ||||
| 
 | ||||
| <ul> | ||||
| 
 | ||||
|   <li> | ||||
|     <strong>Name:</strong> | ||||
|     <%= @clothes.name %> | ||||
|   </li> | ||||
| 
 | ||||
|   <li> | ||||
|     <strong>Location:</strong> | ||||
|     <%= @clothes.location %> | ||||
|   </li> | ||||
| 
 | ||||
|   <li> | ||||
|     <strong>Game:</strong> | ||||
|     <%= @clothes.game %> | ||||
|   </li> | ||||
| 
 | ||||
| </ul> | ||||
| 
 | ||||
| <span><%= link "Edit", to: Routes.clothes_path(@conn, :edit, @clothes) %></span> | ||||
| <span><%= link "Back", to: Routes.clothes_path(@conn, :index) %></span> | ||||
							
								
								
									
										3
									
								
								lib/pokemon_couture_web/views/clothes_view.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								lib/pokemon_couture_web/views/clothes_view.ex
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| defmodule PokemonCoutureWeb.ClothesView do | ||||
|   use PokemonCoutureWeb, :view | ||||
| end | ||||
							
								
								
									
										21
									
								
								priv/repo/migrations/20210628141736_create_clothes.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								priv/repo/migrations/20210628141736_create_clothes.exs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| defmodule PokemonCouture.Repo.Migrations.CreateClothes do | ||||
|   use Ecto.Migration | ||||
| 
 | ||||
|   def change do | ||||
|     create table(:clothes) do | ||||
|       add :name, :string | ||||
|       add :location, :string | ||||
|       add :game, :string | ||||
| 
 | ||||
|       timestamps() | ||||
|     end | ||||
| 
 | ||||
|     create table(:ownerships, primary_key: false) do | ||||
|       add :user_id, references(:users) | ||||
|       add :clothes_id, references(:clothes) | ||||
|     end | ||||
| 
 | ||||
|     create unique_index(:ownerships, [:user_id, :clothes_id]) | ||||
| 
 | ||||
|   end | ||||
| end | ||||
							
								
								
									
										68
									
								
								test/pokemon_couture/shops_test.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								test/pokemon_couture/shops_test.exs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| defmodule PokemonCouture.ShopsTest do | ||||
|   use PokemonCouture.DataCase | ||||
| 
 | ||||
|   alias PokemonCouture.Shops | ||||
| 
 | ||||
|   describe "clothes" do | ||||
|     alias PokemonCouture.Shops.Clothes | ||||
| 
 | ||||
|     @valid_attrs %{game: "some game", location: "some location", name: "some name"} | ||||
|     @update_attrs %{game: "some updated game", location: "some updated location", name: "some updated name"} | ||||
|     @invalid_attrs %{game: nil, location: nil, name: nil} | ||||
| 
 | ||||
|     def clothes_fixture(attrs \\ %{}) do | ||||
|       {:ok, clothes} = | ||||
|         attrs | ||||
|         |> Enum.into(@valid_attrs) | ||||
|         |> Shops.create_clothes() | ||||
| 
 | ||||
|       clothes | ||||
|     end | ||||
| 
 | ||||
|     test "list_clothes/0 returns all clothes" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert Shops.list_clothes() == [clothes] | ||||
|     end | ||||
| 
 | ||||
|     test "get_clothes!/1 returns the clothes with given id" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert Shops.get_clothes!(clothes.id) == clothes | ||||
|     end | ||||
| 
 | ||||
|     test "create_clothes/1 with valid data creates a clothes" do | ||||
|       assert {:ok, %Clothes{} = clothes} = Shops.create_clothes(@valid_attrs) | ||||
|       assert clothes.game == "some game" | ||||
|       assert clothes.location == "some location" | ||||
|       assert clothes.name == "some name" | ||||
|     end | ||||
| 
 | ||||
|     test "create_clothes/1 with invalid data returns error changeset" do | ||||
|       assert {:error, %Ecto.Changeset{}} = Shops.create_clothes(@invalid_attrs) | ||||
|     end | ||||
| 
 | ||||
|     test "update_clothes/2 with valid data updates the clothes" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert {:ok, %Clothes{} = clothes} = Shops.update_clothes(clothes, @update_attrs) | ||||
|       assert clothes.game == "some updated game" | ||||
|       assert clothes.location == "some updated location" | ||||
|       assert clothes.name == "some updated name" | ||||
|     end | ||||
| 
 | ||||
|     test "update_clothes/2 with invalid data returns error changeset" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert {:error, %Ecto.Changeset{}} = Shops.update_clothes(clothes, @invalid_attrs) | ||||
|       assert clothes == Shops.get_clothes!(clothes.id) | ||||
|     end | ||||
| 
 | ||||
|     test "delete_clothes/1 deletes the clothes" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert {:ok, %Clothes{}} = Shops.delete_clothes(clothes) | ||||
|       assert_raise Ecto.NoResultsError, fn -> Shops.get_clothes!(clothes.id) end | ||||
|     end | ||||
| 
 | ||||
|     test "change_clothes/1 returns a clothes changeset" do | ||||
|       clothes = clothes_fixture() | ||||
|       assert %Ecto.Changeset{} = Shops.change_clothes(clothes) | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @ -0,0 +1,88 @@ | ||||
| defmodule PokemonCoutureWeb.ClothesControllerTest do | ||||
|   use PokemonCoutureWeb.ConnCase | ||||
| 
 | ||||
|   alias PokemonCouture.Shops | ||||
| 
 | ||||
|   @create_attrs %{game: "some game", location: "some location", name: "some name"} | ||||
|   @update_attrs %{game: "some updated game", location: "some updated location", name: "some updated name"} | ||||
|   @invalid_attrs %{game: nil, location: nil, name: nil} | ||||
| 
 | ||||
|   def fixture(:clothes) do | ||||
|     {:ok, clothes} = Shops.create_clothes(@create_attrs) | ||||
|     clothes | ||||
|   end | ||||
| 
 | ||||
|   describe "index" do | ||||
|     test "lists all clothes", %{conn: conn} do | ||||
|       conn = get(conn, Routes.clothes_path(conn, :index)) | ||||
|       assert html_response(conn, 200) =~ "Listing Clothes" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "new clothes" do | ||||
|     test "renders form", %{conn: conn} do | ||||
|       conn = get(conn, Routes.clothes_path(conn, :new)) | ||||
|       assert html_response(conn, 200) =~ "New Clothes" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "create clothes" do | ||||
|     test "redirects to show when data is valid", %{conn: conn} do | ||||
|       conn = post(conn, Routes.clothes_path(conn, :create), clothes: @create_attrs) | ||||
| 
 | ||||
|       assert %{id: id} = redirected_params(conn) | ||||
|       assert redirected_to(conn) == Routes.clothes_path(conn, :show, id) | ||||
| 
 | ||||
|       conn = get(conn, Routes.clothes_path(conn, :show, id)) | ||||
|       assert html_response(conn, 200) =~ "Show Clothes" | ||||
|     end | ||||
| 
 | ||||
|     test "renders errors when data is invalid", %{conn: conn} do | ||||
|       conn = post(conn, Routes.clothes_path(conn, :create), clothes: @invalid_attrs) | ||||
|       assert html_response(conn, 200) =~ "New Clothes" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "edit clothes" do | ||||
|     setup [:create_clothes] | ||||
| 
 | ||||
|     test "renders form for editing chosen clothes", %{conn: conn, clothes: clothes} do | ||||
|       conn = get(conn, Routes.clothes_path(conn, :edit, clothes)) | ||||
|       assert html_response(conn, 200) =~ "Edit Clothes" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "update clothes" do | ||||
|     setup [:create_clothes] | ||||
| 
 | ||||
|     test "redirects when data is valid", %{conn: conn, clothes: clothes} do | ||||
|       conn = put(conn, Routes.clothes_path(conn, :update, clothes), clothes: @update_attrs) | ||||
|       assert redirected_to(conn) == Routes.clothes_path(conn, :show, clothes) | ||||
| 
 | ||||
|       conn = get(conn, Routes.clothes_path(conn, :show, clothes)) | ||||
|       assert html_response(conn, 200) =~ "some updated game" | ||||
|     end | ||||
| 
 | ||||
|     test "renders errors when data is invalid", %{conn: conn, clothes: clothes} do | ||||
|       conn = put(conn, Routes.clothes_path(conn, :update, clothes), clothes: @invalid_attrs) | ||||
|       assert html_response(conn, 200) =~ "Edit Clothes" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "delete clothes" do | ||||
|     setup [:create_clothes] | ||||
| 
 | ||||
|     test "deletes chosen clothes", %{conn: conn, clothes: clothes} do | ||||
|       conn = delete(conn, Routes.clothes_path(conn, :delete, clothes)) | ||||
|       assert redirected_to(conn) == Routes.clothes_path(conn, :index) | ||||
|       assert_error_sent 404, fn -> | ||||
|         get(conn, Routes.clothes_path(conn, :show, clothes)) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   defp create_clothes(_) do | ||||
|     clothes = fixture(:clothes) | ||||
|     %{clothes: clothes} | ||||
|   end | ||||
| end | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user