Flop
Flop is an Elixir library for making filtering, ordering and pagination with Ecto a bit easier.
This library is in early development.
Features
- ordering by multiple fields in multiple directions
- offset/limit based pagination
- page number/page size based pagination
- filtering by multiple conditions with diverse operators on multiple fields
- parameter validation
- configurable filterable and sortable fields
To Do
See https://github.com/woylie/flop/projects/1
Installation
Add flop
to your list of dependencies in mix.exs
:
def deps do
[
{:flop, "~> 0.4.0"}
]
end
Usage
Define sortable and filterable fields
If you want the order by and filter fields to be validated, configure the sortable and filterable fields in your Ecto schema like this:
defmodule MyApp.Pet do
use Ecto.Schema
@derive {Flop.Schema,
filterable: [:name, :species], sortable: [:name, :age, :species]}
schema "pets" do
field :name, :string
field :age, :integer
field :species, :string
field :social_security_number, :string
end
end
Querying
The most important functions are Flop.query/2
and Flop.validate/2
. You can
use them like this:
defmodule MyApp.Pets do
import Ecto.Query, warn: false
alias Ecto.Changeset
alias Flop
alias MyApp.{Pet, Repo}
@spec list_pets(Flop.t()) :: {:ok, [Pet.t()]} | {:error, Changeset.t()}
def list_pets(flop \\ %Flop{}) do
with {:ok, flop} <- Flop.validate(flop, for: Pet) do
pets =
Pet
|> Flop.query(flop)
|> Repo.all()
{:ok, pets}
end
end
end
If you didn't derive Flop.Schema as described above and don't care to do so,
just call the validate function without the second parameter:
Flop.validate(flop)
.
Phoenix
If you are using Phoenix, you might prefer to validate the Flop parameters in your controller instead.
defmodule MyAppWeb.PetController do
use MyAppWeb, :controller
alias Flop
alias MyApp.Pets
alias MyApp.Pets.Pet
action_fallback MyAppWeb.FallbackController
def index(conn, params) do
with {:ok, flop} <- Flop.validate(params, for: Pet) do
pets = Pets.list_pets(flop)
render(conn, "index.html", pets: pets)
end
end
end
defmodule MyApp.Pets do
import Ecto.Query, warn: false
alias Flop
alias MyApp.Pets.Pet
alias MyApp.Repo
@spec list_pets(Flop.t()) :: [Pet.t()]
def list_pets(flop \\ %Flop{}) do
Pet
|> Flop.query(flop)
|> Repo.all()
end
end