LoginSignup
11
10

More than 5 years have passed since last update.

Elixirでtrotを使ってみる

Last updated at Posted at 2016-03-07

Trot is an Elixir web micro-framework based on Plug and Cowboy.

TrotはPlugとCowboyで作られたマイクロWebフレームワークらしいです。

rubyのsinatraと同じようなことをelixirでもしたくなったので色々探した結果、trotというパッケージを見つけたのでその使い方を簡単に紹介します。

作る

準備

mix new trot_sample
今回はTrotSampleというプロジェクトをmixで作りました。
まずはmix.exsに依存関係を追加

mix.exs
  def application do
    [application: [:trot]]
  end

  defp deps do
    [{:trot, github: "hexedpackets/trot"}]
  end

設定と実装

READMEに書いてあるようにconfig/config.exsに追記します。

config/config.exs
use Mix.Config

config :trot, :port, 4000
config :trot, :router, TrotSample

今回は最低限の設定で。

あとはメインとなるRouterを書いていきます。

lib/trot_sample.ex
defmodule TrotSample do
  use Trot.Router

  get "/ping" do
    "pong"
  end

  get "double/:number" do
    number |> String.to_integer |> (&(&1 * 2)).() |> Integer.to_string
  end

  post "/echo" do
    {:ok, body, conn} = read_body conn
    body
  end

  post "/hello" do
    conn = fetch_query_params(conn)
    "Hello, #{conn.params["name"]}!"
  end

  get "/json" do
    %{lang: "elixir"}
  end
end

上から順に

  • 単純なGET
  • URL中のパターンマッチ
  • POSTのbodyを返す
  • POSTのクエリパラメータを返す
  • JSONの返却

をしています。

リクエストのbodyはread_body、パラメータはfetch_query_paramsを使う必要があるのですが、READMEには全く書いてなくてものすごく悩みました。結局Plugについて調べている最中に発見しました。

ところでパイプラインの途中で匿名関数を使うときに(&(&1 * 2)).()(fn x -> x * 2 end).()と書かないといけないのはどうにかなりませんかね?

叩く

起動して叩いてみます

$ mix trot.server
$ curl http://localhost:4000/ping
pong
$ curl http://localhost:4000/double/10
20
$ curl -d "are you ok?" http://localhost:4000/echo
are you ok?
$ curl -d "" http://localhost:4000/hello?name=techno
Hello, techno!
$ curl http://localhost:4000/json
{"lang":"elixir"}

まだ試していませんがテンプレートをレンダリングすることもできるようです。

静的コンテンツ

staticの使い方に若干嵌ったので・・・

trotのソースではstaticは以下のように定義されています。

trot.ex
  @static_root Path.relative_to_cwd("priv/static")

~~
~~

  defmacro static(at, from), do: static_plug(at, from)

  defmacro static(at), do: static_plug(at, "/")

  defp static_plug(at, from) do
    quote do
      path = Path.join(@static_root, unquote(from))
      @plugs {Plug.Static, [at: unquote(at), from: path], true}
    end
  end

従って

static.ex
def MyRouter do
  static "/css", "assets"
end

と書くと、内部でPath.join(@static_root, "assets")のようなコードがマクロによって生成されるので、静的コンテンツはpriv/static/assets/以下に置く必要があります。そして、/css/~というパスのリクエストによってコンテンツが返されます。

例えば/staticにファイルを置いて、/assets/~というパスのリクエストによって静的コンテンツを返したい場合は

static.ex
defmodule MyRouter do
  @static_root "/"
  static "/assets", "static"
end

あるいは

static.ex
defmodule MyRouter do
  @static_root "static"
  static "/assets"

と書けば良いわけですね。

参考

hexedpackets/trot: An Elixir web micro-framework.
[Elixir+Trot] Trot-Frameworkを使って"Hello Trot!!"するだけの簡単なお仕事・・・
週刊Elixirライブラリ2015-3 - ハードリカーエンジニア

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10