Getting wet with phoenix
Tags: elixir, phoenix, rest
Published: 2022-09-05 08:01:55

Now a days writing phoenix CRUD application is not a hurdle for beginners. After completing [installation](https://hexdocs.pm/phoenix/installation.html#content) with in few [steps](https://hexdocs.pm/phoenix/up_and_running.html) your initial project is up and running. and we have some magic codes to create new HTML resources with views,controllers and contexts. now we are not going to that part right now, before using those magic codes in your project having a clear picture about context, controllers and views will give a happy path in your coding life. so let us jump to a all those things by a sample phoenix project.

The parts of a html resource in phoenix project is as follows
* Migration
* Schema
* Changeset
* Context 
* Controller 
* View
* Template
* Router

Let's do a project by covering all these steps

#### Create a phoenix project 
```
mix phx.new greeting_cards
We are almost there! The following steps are missing:

    $ cd greeting_card

Then configure your database in config/dev.exs and run:

    $ mix ecto.create

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server

```
Hope you done all step by step, in case of any errors check installation guide

### Let's start with a feature
We created a project named greeting_cards my let us assume its an app for greeting card design collections as an initial step we should feed collection of greeting cards in our database. 
### Migration
```
mix ecto.gen.migration create_greeting_cards

==> greeting_card
Compiling 14 files (.ex)
Generated greeting_card app
* creating priv/repo/migrations/20220903182959_create_greeting_cards.exs

```
Navigate to .exs generated shown in output
Update the file with these scripts to 
```elixir
defmodule GreetingCard.Repo.Migrations.CreateGreetingCards do
  use Ecto.Migration

  def change do
    create table(:greeting_cards) do
      add :name, :string
      add :type, :string
      add :template, :string
      add :print_quality, :string
      add :preview, :string
    end
  end
end
```

And run `mix ecto.migrate`

Will create table "greeting_cards" in your database
### Context
An encapsulation layer for data access and validation, so the schemas are grouped under a context name for more details 
refer [Contexts](https://hexdocs.pm/phoenix/contexts.html#:~:text=In%20Phoenix%2C%20contexts%20often%20encapsulate,build%20out%20our%20web%20application.)

Create
```
lib/greeting_cards/feeder.ex
lib/greeting_cards/feeder/         #Directory
```

### Schema
An Ecto.Schema maps External data into elixir structs, a Schema file contains specification of fields for database table and Changesets to allow filtering, casting, validation and definition of constraints when manipulating structs.
[Schema](https://hexdocs.pm/ecto/Ecto.Schema.html)
[Chngeset](https://hexdocs.pm/ecto/Ecto.Changeset.html)
Here to create our schema for greeting cards
Create
```elixir
lib/greeting_cards/feeder/greeting_card.ex


defmodule GreetingCard.Feeder.GreetingCard do
  use Ecto.Schema
  import Ecto.Changeset

  schema "greeting_cards" do
    field :name, :string
    field :type, :string
    field :template, :string
    field :print_quality, :string
    field :preview, :string
  end

 def changeset(greeting_card, params \\ %{}) do
    greeting_card
    |> cast(params, [:name, :type, :template, :print_quality, :preview])
    |> validate_required([:name, :type, :print_quality])
  end

```
### Write Context functions 
We mapped our database table with an Elixir struct by a Schema module then we can write functions to do CRUD operations 
To write CRUD functions Refer 
[Ecto.Repo](https://hexdocs.pm/ecto/Ecto.Repo.html)

Update `lib/greeting_cards/feeder.ex` 

```elixir
defmodule GreetingCard.Feeder do
  alias GreetingCard.Repo
  alias GreetingCard.Feeder.GreetingCard

  def list_greeting_cards do
    Repo.all(GreetingCard)
  end

  def create_greeting_card(params) do
    %GreetingCard{}
    |> GreetingCard.changeset(params)
    |> Repo.insert()
  end

  def show_greeting_card(id) when not is_nil(id) do
    Repo.get(GreetingCard, id)
  end

  def update_greeting_card(greeting_card, params) do
    greeting_card
    |> GreetingCard.changeset(params)
    |> Repo.update()
  end

  def delete_greeting_card(greeting_card) do
    Repo.delete(greeting_card)
  end
end

```
### Run and test our code using iex shell
So far we are writing codes to create a feature, debugging and running is an another interested part of coding, before running our feature in to a web server let's run that in our [iex](https://hexdocs.pm/iex/IEx.html) shell and make sure all our functions are working as we expected
In terminal project root directory run
`iex -S mix`
Call your functions in shell through module name here
```elixir
iex(2)> GreetingCard.Feeder.create_greeting_card(%{name: "card1",type: "birthday", template: "template1",print_quality: "canva"})
[debug] QUERY OK db=1.4ms queue=2.0ms idle=1173.7ms
INSERT INTO "greeting_cards" ("name","print_quality","template","type") VALUES ($1,$2,$3,$4) RETURNING "id" ["card1", "canva", "template1", "birthday"]
↳ :erl_eval.do_apply/6, at: erl_eval.erl:685
{:ok,
 %GreetingCard.Feeder.GreetingCard{
   __meta__: #Ecto.Schema.Metadata<:loaded, "greeting_cards">,
   id: 1,
   name: "card1",
   preview: nil,
   print_quality: "canva",
   template: "template1",
   type: "birthday"
 }}
iex(3)> GreetingCard.Feeder.list_greeting_cards                                                                 [debug] QUERY OK source="greeting_cards" db=0.9ms idle=1687.7ms
SELECT g0."id", g0."name", g0."type", g0."template", g0."print_quality", g0."preview" FROM "greeting_cards" AS g0 []
↳ :erl_eval.do_apply/6, at: erl_eval.erl:685
[
  %GreetingCard.Feeder.GreetingCard{
    __meta__: #Ecto.Schema.Metadata<:loaded, "greeting_cards">,
    id: 1,
    name: "card1",
    preview: nil,
    print_quality: "canva",
    template: "template1",
    type: "birthday"
  }
]
iex(4)> GreetingCard.Feeder.show_greeting_card(1)
[debug] QUERY OK source="greeting_cards" db=0.5ms queue=0.6ms idle=373.3ms
SELECT g0."id", g0."name", g0."type", g0."template", g0."print_quality", g0."preview" FROM "greeting_cards" AS g0 WHERE (g0."id" = $1) [1]
↳ :erl_eval.do_apply/6, at: erl_eval.erl:685
%GreetingCard.Feeder.GreetingCard{
  __meta__: #Ecto.Schema.Metadata<:loaded, "greeting_cards">,
  id: 1,
  name: "card1",
  preview: nil,
  print_quality: "canva",
  template: "template1",
  type: "birthday"
}
``` 
### Run with server
So far we are working on the data layer of our feature, we have to implement view and controller layers as well. Phoenix project contains a [Routing](https://hexdocs.pm/phoenix/routing.html) Module by default to specify routers. They are the main hubs of phoenix application, They match HTTP requests to controller actions,wire up real-time channel handlers, etc..

Refer [Request Life cycle](https://hexdocs.pm/phoenix/request_lifecycle.html)