Elixir scaffold生成.html.heexの「<%= ～ %>」追加／改修

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はscaffold生成した後でhtml.heexの「<%= ～ %>」部分を追加／改修する方法をまとめます。

# 目的
mixコマンド(今回は`mix phx.gen.live`を使用)を使用してscaffoldした後、html.heexファイル内の「<%= ～ %>」部分を追加／改修する方法を理解する。

## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.17.0
Erlang v27.0
Phoenix 1.7.14


# html.heexファイル内の「<%= ～ %>」部分とは
<%= ～ %>部分とは、Elixirの式と結果をテンプレートファイル(=heexファイル)に補間するためのものです。
<%= ～ %>部分は、`@`を用いて画面表示を行う際に頻繁に使用されます。

https://hexdocs.pm/phoenix/1.7.14/components.html#heex


# 前提
## Phoenixプロジェクト作成
`hello`という名前でPhoenixプロジェクトを作成
```bash:bash
mix phx.new hello
cd hello
mix ecto.create
```
## scaffold実行
```bash:bash
mix phx.gen.live Accounts Users users name:string age:integer
```

```diff_elixir:lib/hello_web/router.ex
 scope "/", HelloWeb do
     pipe_through :browser

     get "/", PageController, :home
     
+    live "/users", UsersLive.Index, :index
+    live "/users/new", UsersLive.Index, :new
+    live "/users/:id/edit", UsersLive.Index, :edit
+
+    live "/users/:id", UsersLive.Show, :show
+    live "/users/:id/show/edit", UsersLive.Show, :edit
   end
```

```bash:bash
mix ecto.migrate
```

## scaffoldされたheexファイルの確認
```diff_elixir:lib/hello_web/live/users_live/index.html.heex
<.header>
  Listing Users
  <:actions>
    <.link patch={~p"/users/new"}>
      <.button>New Users</.button>
    </.link>
  </:actions>
</.header>

<.table
  id="users"
  rows={@streams.users_collection}
  row_click={fn {_id, users} -> JS.navigate(~p"/users/#{users}") end}
>
  <:col :let={{_id, users}} label="Name"><%= users.name %></:col>
  <:col :let={{_id, users}} label="Age"><%= users.age %></:col>
  <:action :let={{_id, users}}>
    <div class="sr-only">
      <.link navigate={~p"/users/#{users}"}>Show</.link>
    </div>
    <.link patch={~p"/users/#{users}/edit"}>Edit</.link>
  </:action>
  <:action :let={{id, users}}>
    <.link
      phx-click={JS.push("delete", value: %{id: users.id}) |> hide("##{id}")}
      data-confirm="Are you sure?"
    >
      Delete
    </.link>
  </:action>
</.table>

<.modal :if={@live_action in [:new, :edit]} id="users-modal" show on_cancel={JS.patch(~p"/users")}>
  <.live_component
    module={HelloWeb.UsersLive.FormComponent}
    id={@users.id || :new}
    title={@page_title}
    action={@live_action}
    users={@users}
    patch={~p"/users"}
  />
</.modal>
```
画面上ではこんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/940965b4-8a2c-680f-e74e-0dd53821ccb1.png)


# 追加してみる
## 標準ライブラリの関数をheexファイルに追加
先ほどのheexファイルの先頭行にElixirの標準ライブラリの関数を追加します

テストを追加します。
```diff_elixir:test/hello_web/live/users_live_test.exs
 describe "Index" do
     setup [:create_users]
 
+ test "hello world", %{conn: conn, users: users} do
+       {:ok, _index_live, html} = live(conn, ~p"/users")
+ 
+       assert html =~ "Hello World!"
+ end
# 以下略
```

テストが通る実装を追加します。
```diff_elixir:lib/hello_web/live/users_live/index.html.heex
+ <p><%= IO.inspect("Hello World!") %></p>
+
 <.header>
   Listing Users
   <:actions>
# 以下略
```
画面上ではこんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/d3bed2b8-74ea-d087-c6cf-f0c4f951a9f3.png)


## テンプレートに実装した関数をheexファイルに追加
`lib/hello_web/controllers/page_html.ex`に新しい関数を１つ追加し、先ほどのheexファイルで呼び出します

テストを追加します。
```diff_elixir:test/hello_web/live/users_live_test.exs
 describe "Index" do
     setup [:create_users]
 
+ test "render today's date", %{conn: conn, users: users} do
+       {:ok, _index_live, html} = live(conn, ~p"/users")
+ 
+       assert html =~ Date.utc_today |> to_string()
+     end
# 以下略
```

テストが通る実装を追加します。
```diff_elixir:lib/hello_web/controllers/page_html.ex
  defmodule HelloWeb.PageHTML do
    use HelloWeb, :html

    embed_templates "page_html/*"

+   def render_today do
+     Date.utc_today()
+   end
  end
```


```diff_elixir:lib/hello_web/live/users_live/index.html.heex
  <p><%= IO.inspect("Hello World!") %></p>
+ <p><%= HelloWeb.PageHTML.render_today %></p>

 <.header>
   Listing Users
   <:actions>
# 以下略
```
画面上ではこんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/0ecc89c4-e0ac-63dc-4c03-8651a69c9b53.png)



# 改修してみる
`Name`, `Age`に加えてデータの追加日を`Registered day`として画面に表示させます

```diff_elixir:lib/hello_web/live/users_live/index.html.heex
 <.table
   id="users"
   rows={@streams.users_collection}
   row_click={fn {_id, users} -> JS.navigate(~p"/users/#{users}") end}
 >
   <:col :let={{_id, users}} label="Name"><%= users.name %></:col>
   <:col :let={{_id, users}} label="Age"><%= users.age %></:col>
+  <:col :let={{_id, users}} label="Registered day"><%= users.inserted_at %></:col>
# 以下略
```
画面上ではこんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/7c228103-b733-8eb3-5bce-4cf06f5e1ce6.png)



# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian




[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！