Phoenixで湯婆婆を実装してみる

# はじめに
- @Nemesis さんの[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)を拝見しまして、私は[Elixir](https://elixir-lang.org/)でやってみました
    - [Elixirで湯婆婆を実装してみる](https://qiita.com/torifukukaiou/items/daec6de40a54978dccc9)
- さらに`湯婆婆`に関する記事のリンク集を作りました
    - [【毎日自動更新】湯婆婆 LGTMランキング！](https://qiita.com/torifukukaiou/items/c8361231cdc56e493245)
- そうして今回はさらに[Phoenix](https://www.phoenixframework.org/)で作ってみたいとおもいます
    - [Phoenix](https://www.phoenixframework.org/)とは、[Elixir](https://elixir-lang.org/)を使ってWebアプリをつくっていけるWebアプリケーションフレームワークです

# 0. 準備
- まずは[Elixir](https://elixir-lang.org/)をインストールしましょう
- 手前味噌な記事ですが[インストール](https://qiita.com/torifukukaiou/items/d04d0273749c41eb50af#0-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)などをご参照ください
- さらには[Phoenix](https://www.phoenixframework.org/)用の準備が必要です
    - 公式ページの[Installation](https://hexdocs.pm/phoenix/installation.html#content)をご参照ください
    - こちらが日本語訳です
        - https://fukuoka-ex.github.io/phoenix-guide-ja/guides/1.5/introduction/installation.html
    - ここでインストールするものに[Elixir](https://elixir-lang.org/)関係以外では、node.jsとPostgreSQLがあげられていますが、今回はPostgreSQLは使いません

# 1. プロジェクト作成

```
$ mix phx.new yubaba --live
$ cd yubaba
```

# 2. ソースコードを書く

- `assets/static/images/chihiro016.jpg`と`assets/static/images/chihiro017.jpg`を置いておく
    - [今月から、スタジオジブリ作品の場面写真の提供を開始します](http://www.ghibli.jp/info/013344/?s=03)から画像をいただきます
    - [【小ネタ】さっそく、ジブリの画像をダウンロードする](https://qiita.com/mine820/items/e2561cbdd1904069fa09)
    - [【小ネタ】さっそく、ジブリの画像をダウンロードする(Elixir)](https://qiita.com/torifukukaiou/items/0bd782a6f9228f6a95d5)

```elixir:lib/yubaba/yubaba.ex
defmodule Yubaba.Yubaba do
  def new_name(""), do: "千"

  def new_name(name) do
    if String.contains?(name, "千") do
      "千"
    else
      String.codepoints(name) |> Enum.random()
    end
  end
end
```
- 何も入力されていない場合には"千"、入力文字列に"千"が含まれていれば"千"、それ以外はランダムに選ぶということにしました

```elixir:lib/yubaba_web/live/yubaba_live.ex
defmodule YubabaWeb.YubabaLive do
  use YubabaWeb, :live_view

  def mount(_params, _session, socket) do
    socket = assign(socket, name: "", submitted: false, new_name: "")
    {:ok, socket}
  end

  def render(assigns) do
    ~L"""
    <h1>湯婆婆</h1>
    <%= if @submitted do %>
      <img src="images/chihiro017.jpg">
    <% else %>
      <img src="images/chihiro016.jpg">
    <% end %>
    <form phx-submit="yubaba">
      <input type="text" name="name" value="<%= @name %>"
        placeholder="契約書だよ。そこに名前を書きな。"
        autofocus autocomplete="off" />

      <button type="submit">
        回答
      </button>
      <%= if @submitted do %>
        <a href="/yubaba">もう一度</a>
      <% end %>
    </form>

    <%= if @submitted do %>
    <pre>
    フン。<%= @name %>というのかい。贅沢な名だねぇ。
    今からお前の名前は<%= @new_name %>だ。いいかい、<%= @new_name %>だよ。分かったら返事をするんだ、<%= @new_name %>!!
    </pre>
    <% end %>
    """
  end

  def handle_event("yubaba", %{"name" => name}, socket) do
    new_name = Yubaba.Yubaba.new_name(name)

    socket =
      assign(socket,
        name: name,
        new_name: new_name,
        submitted: true
      )

    {:noreply, socket}
  end
end
```

```diff:lib/yubaba_web/router.ex
@@ -18,6 +18,7 @@ defmodule YubabaWeb.Router do
     pipe_through :browser
 
     live "/", PageLive, :index
+    live "/yubaba", YubabaLive
   end
```

- ↑↑↑ ここまででもOKです

## おまけ
- ここからはおまけです
- 入力された値と変換後の値をPostgreSQLに保存してみます

```
$ mix phx.gen.live Accounts User users name new_name
```

- どどっとファイルができます
- **まあ気にしないことにしましょう**
- `lib/yubaba_web/router.ex`にパスを追加します

```diff:lib/yubaba_web/router.ex
@@ -19,6 +19,13 @@ defmodule YubabaWeb.Router do
 
     live "/", PageLive, :index
     live "/yubaba", YubabaLive
+
+    live "/users", UserLive.Index, :index
+    live "/users/new", UserLive.Index, :new
+    live "/users/:id/edit", UserLive.Index, :edit
+
+    live "/users/:id", UserLive.Show, :show
+    live "/users/:id/show/edit", UserLive.Show, :edit
   end
```


- 入力値と変換後の値を保存するコードを足します

```diff:YubabaWeb.YubabaLive
   def handle_event("yubaba", %{"name" => name}, socket) do
     new_name = Yubaba.Yubaba.new_name(name)
 
+    {:ok, %Yubaba.Accounts.User{}} =
+      Yubaba.Accounts.create_user(%{name: name, new_name: new_name})
+
     socket =
       assign(socket,
         name: name,
```

- あとは[LiveViewでinfinite scroll (Elixir/Phoenix)](https://qiita.com/torifukukaiou/items/c3e37813c6c32fb6d5d2)なんてのをやるとおもしろいかもしれません
- 本題とははずれるので紹介のみにしておきます
- その他、ここで書いていない細かな修正などあるのですが、細かいですし、そろそろ面倒になってきたのでソースコードを公開しておきます
- [TORIFUKUKaiou/yubaba](https://github.com/TORIFUKUKaiou/yubaba)




# 3. 実行

```
$ mix phx.server
```

Visit: `http://localhost:4000/yubaba`

- 最初にこの画像を表示して
    - http://www.ghibli.jp/gallery/chihiro016.jpg
- 名前を入力して「回答」ボタンを押したら、1文字選んでこの画像を表示するようにしました
    - http://www.ghibli.jp/gallery/chihiro017.jpg
- 常識の範囲[^1]内かどうかはわからないので、湯婆婆を使った画像はここには載せないことにします

[^1]: http://www.ghibli.jp/info/013344/?s=03 には、「常識の範囲でご自由にお使いください」と書いてあります

![スクリーンショット 2020-11-09 0.05.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/b9648b75-f552-ce27-ea80-192da94ed165.png)

![スクリーンショット 2020-11-09 0.06.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/b2e5f43d-7afd-d2a6-2b3b-f4ff42297b52.png)


# Wrapping Up :lgtm: :qiita-fabicon: :lgtm:
- @momeemtさんの[記事](https://qiita.com/momeemt/items/c4163f71a9b2d4408935#%E6%9C%80%E5%BE%8C%E3%81%AB)にある通り、入力を受け取ってそれを変換して出力するというのは、プログラミングの基本ーー大きく言うと、つまり`湯婆婆`はこれからの`"Hello, World"`における例題の一つのような気がしています
    - 将棋の[原田泰夫](https://ja.wikipedia.org/wiki/%E5%8E%9F%E7%94%B0%E6%B3%B0%E5%A4%AB)九段が提唱された**三手の読み（こうやる、こう来る、そこでこう指す）**に通じるものがあるような気がします
    - [令和のHello World!](https://qiita.com/everylittle/items/aae58c241194c0e5f515#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)との呼び声も！(@everylittle さん)
- Enjoy [Elixir](https://elixir-lang.org/) !!! :rocket::rocket::rocket: