Edited at

Elixirでtrotを使ってみる

More than 3 years have passed since last update.


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 - ハードリカーエンジニア