Phoenix 動作検証 (3)
memo
コンテナ関連について気になったので Dockerhub 探してみることに。
とりあえず elixir については image が存在している (elixir:1.16.1-slim を使用)
Phoenix は Dockerfile の中で mix で云々している
蛇足ですが distillery は基本的に使わない (はず)
これデフォ、ってことで確認すすめます。参照しているエントリは以下です。
追記
見てるドキュメントが古そうなのでやり直します。以下はあまり参考にならないかと。
ソース確認
スキーマから。というか changeset とは何かと。
@doc false
def changeset(task, attrs) do
task
|> cast(attrs, [:content, :state])
|> validate_required([:content, :state])
end
ちなみにコンテキストでのデータ生成時に以下な形で呼び出しています。
@doc """
タスクを作成する。
"""
def create_task(attrs \\ %{}) do
%Task{}
|> Task.changeset(attrs)
|> Repo.insert()
end
あと、Ecto.Changeset というものを import していますね。ググッてみたら以下が出てきました。
ええと、上の changeset の例だと
構造体、修正な引数から
cat で Changeset を作って
validation しています
という理解で良いのかしら。問題なければ Repo.insert に渡す情報が戻される、という事で。
コントローラも順に確認を。まず以下の部分。
alias TodoPhoenix.Todo
alias TodoPhoenix.Todo.Task
これは完全修飾なしで使います、って理解で良いのかしら。というか直上に use ってのもありますね。
use TodoPhoenixWeb, :controller
このあたりの意味を一度確認しておきたい。
use については コントローラーにて「モジュール定義の下の最初の行では、HelloWeb モジュールの using/1 マクロを呼び出しており、いくつかの便利なモジュールをインポートしています。」という記載があります
別途 The ‘use’ Macro in Elixir. を確認のこと
で、lib/todo_phoenix_web.ex 見てみるに controller って手続きが定義されてますね。
def controller do
quote do
use Phoenix.Controller,
formats: [:html, :json],
layouts: [html: TodoPhoenixWeb.Layouts]
import Plug.Conn
import TodoPhoenixWeb.Gettext
unquote(verified_routes())
end
end
いくつかの便利なモジュールをインポート、ってのがこれ、って理解で良いはず。あと alias ですが alias, require, and import にて
alias Math.List
は
alias Math.List, as: List
と同義、って記載がありました。なるほど。以降の手続き定義の部分が以下。
def index(conn, _params) do
tasks = Todo.list_tasks()
render(conn, "index.json", tasks: tasks)
end
def create(conn, %{"task" => task_params}) do
case Todo.create_task(task_params) do
{:ok, %Task{}} ->
send_resp(conn, :created, "")
{:error, _} ->
send_resp(conn, :unprocessable_entity, "")
end
end
def create(conn, _), do: send_resp(conn, :bad_request, "")
send_resp は body が無いレスポンスを戻したい場合に使う、とのこと
:created とか :unprocessable_entity とか :bad_request はステイタスのはず
あと create_task の戻りがどうなっているのか気になります
insert の戻り、なのか
そゆ意味では定義が以下、なんですが
def create_task(attrs \\ %{}) do
%Task{}
|> Task.changeset(attrs)
|> Repo.insert()
end
そもそもこの %Task{} とは一体何なのか、確認必要。
Elixir Ecto のまとめ によると Ecto.Schema は DB テーブルを Elixir struct に map するために使われる、とのこと
なので上の create_task で使われている %Task{} は空の struct で
create で match させるのに使われているのは型の表現、という理解で良いのかしら (このあたり若干微妙なので再度アレを確認)
json を出力する view の作成も行なっています。
defmodule TodoPhoenixWeb.TaskView do
use TodoPhoenixWeb, :view
alias TodoPhoenixWeb.TaskView
def render("index.json", %{tasks: tasks}) do
%{data: render_many(tasks, TaskView, "task.json")}
end
def render("task.json", %{task: task}) do
%{
id: task.id,
content: task.content,
state: task.state
}
end
end
で、これが動かない。対処が以下。
lib/todo_phoenix_web.ex に view メソド追加
mix.exs に {:phoenix_view, "~> 2.0"}, 追加して mix deps.get 実行
で、以下実行してみるに落ちてます。
# curl http://localhost:4000/api/tasks
ちなみにルーティング定義については以下を追加してるのですがどうなのか。
scope "/api", TodoPhoenixWeb do
pipe_through :api
resources "/tasks", TaskController, only: [:create, :index] # 追加
end
routing 情報確認したら出力されてますね。
# mix phx.routes
GET / TodoPhoenixWeb.PageController :home
GET /api/tasks TodoPhoenixWeb.TaskController :index
POST /api/tasks TodoPhoenixWeb.TaskController :create
コンソールには以下な出力が。
[error] GenServer #PID<0.874.0> terminating
** (UndefinedFunctionError) function TodoPhoenixWeb.TaskController.init/1 is undefined (module TodoPhoenixWeb.TaskController is not available)
TodoPhoenixWeb.TaskController.init(:index)
(phoenix 1.7.11) lib/phoenix/router.ex:484: Phoenix.Router.__call__/5
(todo_phoenix 0.1.0) lib/todo_phoenix_web/endpoint.ex:1: TodoPhoenixWeb.Endpoint.plug_builder_call/2
確認してみるにコントローラなソースコード保存してませんでした。次に出てきたのは以下な不具合。
[error] GenServer #PID<0.776.0> terminating
** (ArgumentError) no "index" json template defined for TodoPhoenixWeb.TaskJSON (the module does not exist)
(phoenix_template 1.0.4) lib/phoenix/template.ex:248: Phoenix.Template.render_with_fallback/4
(phoenix_template 1.0.4) lib/phoenix/template.ex:126: Phoenix.Template.render_to_iodata/4
なんかそもそも的に api の作り方がダウトな気がしてきたのでドキュメント見て修正。別途でドキュメントの方法でやり直す。
この記事が気に入ったらサポートをしてみませんか?