[Elixir ORM #0] 开始
工作中重度使用 Elixir,之前一直是用 erlport 包装了 sqlalchemy ,但在 Elixir 里用起来却非常不舒服,于是转头去研究 ecto ,然后发现几个地方用起来不太舒服,具体哪里就不在这里吐槽了,总之就是决定自己搞一套类 ORM 的东西,因为个人看来 ORM 和 OO 是绝配,不适合在 FP 中搞,写 maru 的时候从语法级别抄 grape 抄出来的不卫生宏的坑还没填上,所以这次只参考 AR 的 query 语法,其它完全针对 Elixir 语言设计。
基本的语法已经设计完成,因为以下三个原因项目不能开源,所以决定写一系列 blog 记录开发流程。
- 业务针对性很强,几乎没有通用性。
- 使用了 `~>` 和 `<~` 两个运算符,容易和别的库冲突。
- 功能极简,作为微服务设计,单项目使用没有优势。
从开始到基本的 demo 跑通大约用了一周的时间,取名 Ench。
Repo & Model 定义设计如下:
config :ench, Repo, adapter: Ench.Adapters.MySQL, poolsize: 2, hostname: "127.0.0.1", port: 3306, database: "test", username: "u", password: "p" defmodule Repo do use Ench.Model.Repo end defmodule Resume do use Repo, table: "resumes" end defmodule Collection do use Repo, table: "collections" end defmodule User do use Repo, table: "users" use Ench expose :resumes, [lazy: true, with: user] do Resume ~> where(%{user_id: user[:id]}) end def collect_job(user, job_id) do Collection <~ ins(%{user_id: user[:id], job_id: job_id}) end end
DSL 设计如下:
调用:
u = User ~> find(1) # find_by(%{id: 1}) u[:resumes] ~> all u ~> collect_job(1)
查:
User ~> where("age > ?", [20]) ~> limit(10) ~> offset(10) ~> all User ~> where("age > :age", %{age: 20}) ~> order(:id, :desc) ~> all User ~> where(%{name: "falood"}) ~> first
增:
User <~ ins(%{name: "falood", phone: "1333333333"})
改:
user = User ~> find(1) user <~ set(%{name: "neko"}) user <~ inc(%{age: 1})
删:
user = User ~> find(1) user <~ del
开发过程中,池用的 pooler,postgres 驱动用的 postgrex ,这些当然不是重点了,真正想记录的是以下两点:
待续