Help us understand the problem. What is going on with this article?

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

techno-tanoC
Elixir, Haskell, Ruby, Rustが好き
mixi
全ての人に心地よいつながりを
http://mixi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした