Relax.Resource.FetchAll behaviour

Include in your resource to respond to GET / and GET /?filter[foo]=bar.

Typically brought into your resource via use Relax.Resource.

FetchAll defines three callback behaviours, all of which have a default, overrideable implementation.

In addition this module uses Relax.Resource.Fetchable, for shared model lookup logic with Relax.Resource.FetchOne.

Types

fetchable :: module | Ecto.Query.t | list

Callbacks

fetch_all/1

Specs:

  • fetch_all(Plug.Conn.t) :: Plug.Conn.t | fetchable

Lookup a collection to return.

This often returns an Ecto.Query or and Ecto.Model module name that has not yet been sent to the repo. Relax will execute the query after filtering and format the response appropriately.

# Return all models
def fetch_all(_conn), do: MyApp.Models.Post

# Return models limited to the current_user
def fetch_all(conn), do: Ecto.assoc(conn.assigns[:current_user], :posts)

It may also return a list of structs/models:

def fetch_all(_conn), do: [%Post{title: "foo"}, %Post{title: "bar"}]

A conn may also be returned:

def fetch_all(conn), do: halt send_resp(conn, 401, "no posts for you")

By default it returns the value of fetchable/1 directly:

def fetch_all(conn), do: fetchable(conn)
fetch_all_resources/1

Specs:

  • fetch_all_resources(Plug.Conn.t) :: Plug.Conn.t

This callback can be used to completely override the fetch_all action.

It accepts a Plug.Conn and must return a Plug.Conn.t

filter/3

Specs:

Defines allowed filters for your resource.

By default filters are ignored unless defined. Filters recieve the filter keyword, the query or collection returned from fetch_all/1 and the filter value.

Examples:

# Ecto
def filter("search", query, value) do
  Ecto.Query.where(queryable, [p], ilike(a.body, ^"%#{value}%"))
end

# Lists
def filter("popular", posts, value) do
  Enum.filter(posts, fn(p) -> p.likes > 10 end)
end
sort/3

Specs:

Defines allowed sort fields for your resource.

By default sort params are ignored unless defined. Sorts recieve the field, the query or collection returned from fetch_all/1 and the atom :asc or :desc.

Examples:

# Ecto (asc)
# /resource/?sort=likes,rating
def sort("likes", query, :asc) do
  Ecto.Query.order_by(query, [t], asc: :likes)
end
def sort("rating", query, :asc) do
  Ecto.Query.order_by(query, [t], asc: :rating)
end

# Lists (desc)
# /resource/?sort=-name
def sort("name", list, :desc) do
  Enum.sort_by(list, &(&1.name)) |> Enum.reverse
end