guide/custom_queries.md

# Custom Queries

![alt text](assets/custom_query_execution_flow.jpg)

- **Filtering (Optional)**: `@callback filters(arg :: any) :: [(any() -> {:ok, nil} | {:error, bitstring()})]`
  
  During filtering we apply over input a list of functions `(any() -> {:ok, nil} | {:error, bitstring()})` that will take the input arguments and will return :ok, or :error with error message. 

  *Only in case all the the filters will fails (i.e. all will answers with {:ok, ...}) then will start before stage.*
- **Before (Optional)**: `@callback before(arg :: any) :: {:ok, any()} | {:error, any()}` 

  On before, we can prepare the arguments that will needed the query, and also we can avoid the execution returning `{:error, ...}`.
  
  *Only in case that before stage returns `{:ok, args}`, the flows will execute the query.*
- **Query:** ` @callback query(arg :: any) :: String.t()`
 
  On query method we can focus on write our Surreal DB SQL.


- **After (Optional)**:   
  - `@callback ok(response :: any) :: any()`
  In case the execution will be succesfull for all the responses (internally we used `SurrealEx.Response.all_status_ok?/1`) the flow will execute the `ok(response)`.
   
  - `@callback error(response :: any) :: any()`
   In case the execution will be unsuccess for all the responses (internally we used `SurrealEx.Response.all_status_ok?/1`) the flow will execute `error(response)`.

## Example 
```elixir
  defmodule ExampleFlow do
    use SurrealEx.Query,
      conn: SurrealExTest.QueryFiltersTest.Conn

    # its optional
    def filters(_args) do
      [
        ArgsChecker.required(:price_max),
        ArgsChecker.should_be(:price_max, :float),
        ArgsChecker.greater_than(:price_max, 0.0)
      ]
    end

    # before.. as you see on test its optional

    # query callback is mandatory.
    def query(args) do
      "SELECT * FROM car WHERE price <= #{args.price_max}"
    end

    # its optional
    def ok(response) do
      {:ok, response.result}
    end

    # its optional
    def error(_response) do
      {:error, "not expected case"}
    end

  end
```

Filtering process return us, string errors.

```elixir
  test "We expected that on before function checks args." do
    args = %{}
    {:error, detail} = ExampleFlow.run(args)

    assert detail == [
      "'price_max' is required",
      "'price_max' should be float",
      "'price_max' should be greater than 0.0"
    ]

    args = %{
      price_max: "15000.00"
    }
    {:error, detail} = ExampleFlow.run(args)

    assert detail == [
      "'price_max' should be float",
      "'price_max' should be greater than 0.0"
    ]
  end
```

We can see success execution test.

```
  test "Simple query testing" do
    args = %{
      price_max: 15000.00
    }
    {:ok, list_cars} = ExampleFlow.run(args)

    assert Enum.map(list_cars, fn car -> car["price"] <= 15000 end)
      |> Enum.all?
  end
```