类似 Ruby Grape 项目的 Elixir RESTFul 框架 Maru

作者 falood 所属板块 新闻项目
自从用 grape 开发过 API,从此爱不释手,从开坑 [maru](https://github.com/falood/maru) 到现在也一年多了,从 elixir 0.11 一路跟过来,也遇到了很多问题。现在 elixir 渐渐成熟,elixir 的 web 项目也越来越多,借此推广下这个框架 :D ### 为什么会有 maru 学习 elixir 的人应该都知道 [phoenix](http://www.phoenixframework.org) ,毫无疑问 `phoenix` 是个非常棒的 elixir web 框架,但就像 ruby 中有 `rails` 并没有影响 `sanatra` 和 `grape` 这种新框架的出现。`maru` 也是基于 plug 开发的框架,可以无缝拉入 `phoenix` 作为 restful server。 ### maru 有什么特点 maru 的灵感来源是 [grape](https://github.com/intridea/grape),甚至大多数的地方在语法层面上保持一致,如果熟悉 `grape` 是非常容易上手的,这里简单介绍一下 maru 的 DSL #### 路由 以下路由方案对应了 '/users/:id' 这个 url 的 `get`, `post` 和 `delete` 方法: ```elixir resource :users do route_param :id do get do %{user: XXX} |> json end post do %{result: :success} |> json end delete do %{result: :success} |> json end end end ``` 同时 `resource` 是可以嵌套的,也支持 `get` 、`post` 等宏的路径参数,例如: ```elixir resources :level1 do resource :level2 do get do XXX end end end get "/users/:id" do XXX end ``` #### 参数 参数的用法同样类似 `grape`,但根据 elixir 的语言改变了一些名称,比如说 `grape` 里的 Hash 改成了 Map,Symble 改成了 Atom 等。 ```elixir params do requires :age, type: Integer, values: 18..65 requires :sex, type: Atom, values: [:male, :female], default: :female group :name, type: Map do requires :first_name requires :last_name end optional :intro, type: String, regexp: ~r/^[a-z]+$/ optional :avatar, type: File optional :avatar_url, type: String exactly_one_of [:avatar, :avatar_url] end post do IO.inspect params end ``` ### 在 phoenix 框架中使用 maru 1. mix.exs 的 deps 里加入 ```elixir {:maru, github: "falood/maru"} ``` 2. 编写 maru router ```elixir defmodule MyAPP.API do use Maru.Router get do "It Works!" |> text end end ``` 3. endpoint.ex 里 加一行 ```elixir plug Maru.Plugs.Forword, at: "/api", to: MyAPP.API ``` 这样就把 `/api` 下的请求 forward 到 maru 了,其它的请求继续走 phoenix,[这里](https://github.com/falood/maru_examples/tree/master/phoenix_maru)有个示例。 PS. 目前 hex 里的最新版是 0.2.7,`forword` 的特性已经进入 master分支,会在 hex 0.2.8 中发布。 ### 总结 更多的特性就不在这里写了,非常欢迎喜欢 `grape` 的童鞋试用 [maru](https://github.com/falood/maru) ,也非常欢迎拍砖或贡献代码。 PS. 希望 github 上的 issue 和 commit 都使用英文。不是为了装 B,虽然我自己英文也比较烂,但中文的 commit 过多,会导致无法与国外的牛人交流,望理解。
13 回复
  • bareilles 发表
    狗头哥哥。顶你。写完这个你已经是dsl高手了吧? 你对类sinatra的框架怎么看呢?有没有必要写个elixir版的sinatra?
  • falood 发表
    [@bareilles](/users/44) 多谢多谢!DSL 的话我觉得是 elixir 把 DSL 封装地太易用了,这个项目确实学到了很多 DSL 的东西。我对 sinatra 不熟,没办法评价呀!不过能火肯定是有原因的,虽然 rails 非常易用,但是太重了吧。
  • bareilles 发表
    [@falood](/users/43) chris mccord也说了,elixir来写dsl那叫一个爽。。。 仰慕大神啊,要学元编程有什么好资料呢?还是看完官网的macro入门就能直接上手了?
  • falood 发表
    [@bareilles](/users/44) 把官网的 macro 看一下,就可以写了,写的时候分清「编译时变量」和「运行时变量」就好了,上手很快。
  • hex 发表
    :thumbsup:
  • xavier 发表
    :+1
  • xavier 发表
    :+1:
  • lidashuang 发表
    [@bareilles](/users/44) plug基于就等于sinatra了, plug有简单的router http://hexdocs.pm/plug/Plug.Router.html
  • 农民也很疯狂 发表
    学习了
  • ruchee 发表
    :+1:
  • icn 发表
    请问 maru 有没有类似 rails 的 ActiveModel::Serializer 类似的支持
  • falood 发表
    [@icn](/users/275) 时隔一年多,终于回复这个问题了 https://github.com/elixir-maru/maru_entity
  • holulu 发表
    [@falood](/users/43) macro 的确是很迷人的特性,注意分清「编译时变量」和「运行时变量」也是真正玩过的才说得出来。