View Source LibEcto (lib_ecto v0.1.0)
LibEcto is a simple wrapper for ecto, make it much easier for daily use.
why-libecto
Why LibEcto
Ecto is a great library, but it's a little bit verbose for daily use.
For example, imaging you have a schema like this:
defmodule Sample.Schema do
use Ecto.Schema
@primary_key {:id, EctoKsuid, autogenerate: true}
schema "test" do
field :name, :string
field :value, :string
timestamps()
end
def changeset(m, params) do
m
|> cast(params, [:name, :value])
end
end
For most common use case, you need to write a lot of boilerplate code to do simple CRUD operation:
defmodule Sample.DB do
alias Sample.Schema
alias Sample.Repo
import Ecto.Changeset
def insert_one(params) do
Schema.changeset(%Schema{}, params)
|> Repo.insert()
end
def update_one(m, params) do
m
|> change(params)
|> Repo.update()
end
def delete_one(m) do
Repo.delete(m)
end
def get_by_id(id) do
Repo.get(Schema, id, select: [:id, :name, :value])
end
def get_by_id_array(id_array) do
Repo.all(from m in Schema, where: m.id in ^id_array, select: [:id, :name, :value])
end
def get_by_name(name) do
Repo.get_by(Schema, name: name, select: [:id, :name, :value])
end
#... more boilerplate code
# - get by name array
# - get by page
# - get by prefix
end
But!!!!!! With LibEcto, you can code like this:
defmodule Sample.DB do
use LibEcto
repo: Sample.Repo,
schema: Sample.Schema,
columns: [
:id,
:name,
:value
],
filters: [
:id,
:name
]
def filter(:id, dynamic, %{"id" => value}) when is_bitstring(value),
do: {:ok, dynamic([m], ^dynamic and m.id == ^value)}
def filter(:id, dynamic, %{"id" => value}) when is_list(value),
do: {:ok, dynamic([m], ^dynamic and m.id in ^value)}
def filter(:name, dynamic, %{"name" => value}) when is_bitstring(value),
do: {:ok, dynamic([m], ^dynamic and m.name == ^value)}
def filter(:name, dynamic, %{"name" => {"like", value}}) when is_bitstring(value),
do: {:ok, dynamic([m], ^dynamic and like(m.name, value))}
def filter(:name, dynamic, %{"name" => value}) when is_list(value),
do: {:ok, dynamic([m], ^dynamic and m.name in ^value)}
def filter(_, dynamic, _), do: {:ok, dynamic}
# you can use ecto's ability to build complicate query or update or transaction if GenericDB can't satisfy your need
def other_complicated_query_or_update() do
# do something
end
end
LibEcto will generate all the boilerplate code for you, and you can focus on your business logic:
iex> Sample.DB.create_one(%{name: "test", value: "testv"})
{:ok, %Simple.Schema{id: "2JIebKci1ZgKenvhllJa3PMbydB", name: "test", value: "testv"}}
iex> Sample.DB.get_one(%{name: "test"})
{:ok, %Simple.Schema{id: "2JIebKci1ZgKenvhllJa3PMbydB", name: "test", value: "testv"}}
iex> Sample.DB.get_one(%{name: "not-exists"})
{:ok, nil}
iex> Sample.DB.get_one!(%{name: "not-exists"})
{:error, 404}
iex> {:ok, m} = Sample.DB.get_one(%{name: "test"})
iex> Sample.DB.update_one(m, name: "test2")
{:ok, %Simple.Schema{id: "2JIebKci1ZgKenvhllJa3PMbydB", name: "test2", value: "testv"}}
installation
Installation
The package can be installed by adding lib_ecto
to your list of dependencies in mix.exs
:
def deps do
[
{:lib_ecto, "~> 0.1.0"}
]
end