Elixir + Phonenix でWebアプリ作る時の基本まとめ: コントローラ
Elixir + Phonenix でWebアプリ作る時の基本まとめ
コントローラを単体で生成する
この記事ではモデルで作成したCity
モデルを使ってデータベースの参照・変更を行うコントローラを実装する。
が、いきなりデータベースと連携すると混乱しそうなので、もっとも簡単なコントローラ単体で動作する機能から作っていこう。
コントローラのファイルを作る
コントローラを単体で作る時は、単にアプリの controller
ディレクトリ内にファイルを作ればいい。この時注意が必要なのは命名規則くらい。 [ほげほげ]_controller.ex
というファイル名がそれにあたる。
今回で言えば、City
という名前で作りたいのでコントローラ名は city_controller.ex
となる。
コントローラを作る場所は lib/[アプリ名]_web/controller/
の下。
今回はlib/kuroneko_web/controller/city_controller.ex
になる。
defmodule KuronekoWeb.CityController do
use KuronekoWeb, :controller
alias Kuroneko.City
def index(conn, _params) do
text(conn, "This is City Controller!")
end
end
作ったのは 関数がたった一つindex
だけの簡単なコントローラ。
しかも、テンプレートを使わなくて良いようにtext/2
を使っている。
ルーターにルートを追加する
続いて、サーバーへのリクエストがこのコントローラに届くように、ルーターを変更する。
(省略)
scope "/", KuronekoWeb do
pipe_through :browser
get "/", PageController, :index
resources "/magazines", MagazineController
get "/city", CityController, :index
end
(省略)
やったことは、既にあるscopeの中に
get "/city", CityController, :index
を追加しただけ。これで http://localhost:4000/city
にアクセスすれば、先程作ったCityControllerのindex関数が実行される。早速やってみよう。
Webサイトが表示されて、
This is City Controller!
と文字が表示されていればOK。
データベースのレコードを参照する関数を作る。
次はデータベースの内容を表示するアプリを作ってみる。
その前に、これまで色々やってきててデータベースにゴミが溜まってるかもしれないので一旦削除しよう。
$ mix ecto.reset
これでデータベースは空になる。
続いてデータベースにいくつかレコードを追加する。まだレコードを登録する関数は実装していないので、ここはiexからレコードを追加しよう。
$ iex -S mix
次のようにレコードを追加する。
Repo.insert(City.changeset(%City{}, %{prefectures_code: "32", city_code: "32201", name: "松江市", population: 206200}))
Repo.insert(City.changeset(%City{}, %{prefectures_code: "31", city_code: "312011", name: "鳥取市", population: 193700}))
Repo.insert(City.changeset(%City{}, %{prefectures_code: "40", city_code: "40132", name: "福岡市", population: 1539000}))
これで3つのレコードが追加された。
関数の追加
そして先程の CityController
に新たな関数を追加する。
defmodule KuronekoWeb.CityController do
use KuronekoWeb, :controller
alias Kuroneko.City
alias Kuroneko.Repo
import Ecto.Query
def index(conn, _params) do
text(conn, "This is City Controller!")
end
def get(conn, %{"city_code" => code}) do
[{city_name, population} | _tail] = City
|> where([city], [city_code: ^code])
|> select([city], {city.name, city.population})
|> Repo.all
text(conn, "都市名:#{city_name} 人口:#{population}")
end
end
import Ecto.Query
の追加を忘れないように要注意。
さらにルーターにルーティング情報を追加
(省略)
scope "/", KuronekoWeb do
pipe_through :browser
get "/", PageController, :index
resources "/magazines", MagazineController
get "/city", CityController, :index
get "/city/:city_code", CityController, :get
end
(省略)
注目すべきところは、ルーターでは市町村コードを :city_code
として受け取って、コントローラでは
def get(conn, %{"city_code" => code}) do
のようにして取り出している点。
さて、それでは以下にアクセスしてみよう。
都市名: 福岡市 人口: 1539000
のように表示されていれば成功。
さらに
にもアクセスしてみる。都市名:鳥取市 人口:193700
のように表示されていれば成功。
次回はテンプレートを使って表示や保存をしてみる。
それではお疲れ様でした。
Discussion