パパエンジニアのポエム

奥さんと娘ちゃんへの愛が止まらない

Elixir - Phoenixで株価を表示する(前編)

MySQLに入っている株価データを表示する。
ページ構成としてはHome(月別カレンダー)とVolume(日別出来高ランキング)の2つ。
今回はHomeだけ。

Routing

ルーティングでのポイントは、HomeControllerへのルートは引数有り無しのに種類用意すること。
web/router.exが以下。

defmodule StockScraping.Router do
  use StockScraping.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", StockScraping do
    pipe_through :browser

    get "/", HomeController, :index
    get "/:date", HomeController, :index

    get "/volume/:date", VolumeController, :index
  end
end

HomeController

ここでは引数で受けた文字列をDateにキャストしている。
引数がない場合は、現在時刻を使用する。
(キャスト方法は本当にこれであってるんだろうか…)

render conn, "index.html", items: itemsとすることでテンプレートで@itemsを参照可能になる。
web/controllers/home_controller.exの最終形が以下。

defmodule StockScraping.HomeController do
  use StockScraping.Web, :controller

  def index(conn, params) do
    target_date = case params do
      %{"date" => date} -> case Date.from_iso8601(date) do {:ok, value} -> value end
      _ -> now()
    end

    items = Repo.all(StockScraping.YahooVolumeDate)
      |> Enum.filter(fn(x) ->
        x.date.year == target_date.year
        && x.date.month == target_date.month
      end)

    render conn, "index.html", items: items
  end
end

HomeView

ViewへはDateをstringに変換する関数を作成し、テンプレートから呼び出す。
あえてパターンマッチングで実装してみた。
web/views/home_view.exが以下。

defmodule StockScraping.HomeView do
  use StockScraping.Web, :view

  def convert(date) do
    case Timex.format(date, "{YYYY}-{0M}-{D}") do {:ok, value} -> value end
  end
end

HomeTemplete

UIおいといてとりあえず表示させる。
ポイントはvolume_path(@conn, :index, convert(item.date))
VolumeControllerのIndexアクションへのURLをクエスパラメータ付きでレンダリングする処理。
Routingのget "/volume/:date", VolumeController, :indexでルートを追加しないと例外でる。

<h3>カレンダー</h3>
<ul>
  <%= for item <- @items do %>
    <li>
      <a href="<%= volume_path(@conn, :index, convert(item.date)) %>"><%= item.date %></a>
    </li>
  <% end %>
</ul>

これで一旦株価を更新した日付の一覧を表示できた。