🥾

Elixir + Phonenix でWebアプリ作る時の基本まとめ: コントローラ

4 min read

Elixir + Phonenix でWebアプリ作る時の基本まとめ

  1. 環境構築
  2. データベースの準備とWebアプリの起動
  3. scaffoldぽいやつで最初のコントローラ、モデル、ビューを作る
  4. モデル
  5. コントローラ

コントローラを単体で生成する

この記事ではモデルで作成したCityモデルを使ってデータベースの参照・変更を行うコントローラを実装する。

が、いきなりデータベースと連携すると混乱しそうなので、もっとも簡単なコントローラ単体で動作する機能から作っていこう。

コントローラのファイルを作る

コントローラを単体で作る時は、単にアプリの controller ディレクトリ内にファイルを作ればいい。この時注意が必要なのは命名規則くらい。 [ほげほげ]_controller.ex というファイル名がそれにあたる。
今回で言えば、Cityという名前で作りたいのでコントローラ名は city_controller.ex となる。

コントローラを作る場所は lib/[アプリ名]_web/controller/の下。
今回はlib/kuroneko_web/controller/city_controller.exになる。

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を使っている。

ルーターにルートを追加する

続いて、サーバーへのリクエストがこのコントローラに届くように、ルーターを変更する。

lib/kuroneko_web/router.ex
(省略)

  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関数が実行される。早速やってみよう。

http://localhost:4000/city

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 に新たな関数を追加する。

lib/kuroneko_web/controller/city_controller.ex
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の追加を忘れないように要注意。

さらにルーターにルーティング情報を追加

lib/kuroneko_web/router.ex
(省略)

  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

のようにして取り出している点。

さて、それでは以下にアクセスしてみよう。

http://localhost:4000/city/40132
都市名: 福岡市 人口: 1539000

のように表示されていれば成功。

さらに

http://localhost:4000/city/312011
にもアクセスしてみる。
都市名:鳥取市 人口:193700

のように表示されていれば成功。

次回はテンプレートを使って表示や保存をしてみる。
それではお疲れ様でした。