Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/dockyard/inquisitor

Composable query builder for Ecto
https://github.com/dockyard/inquisitor

composable-queries elixir phoenix

Last synced: about 2 months ago
JSON representation

Composable query builder for Ecto

Lists

README

        

# Inquisitor [![Build Status](https://secure.travis-ci.org/DockYard/inquisitor.svg?branch=master)](http://travis-ci.org/DockYard/inquisitor)

Easily build composable queries for Ecto.

**[Inquisitor is built and maintained by DockYard, contact us for expert Elixir and Phoenix consulting](https://dockyard.com/phoenix-consulting)**.

## Usage

Adding Inquisitor to a project is simple:

```elixir
defmodule MyApp.PostController do
use Inquisitor

def index(conn, params) do
posts =
App.Post
|> build_query(conn, params)
|> Repo.all()

json(conn, posts)
end
end
```

After `use Inquisitor` `build_query/3` is added to
the `MyApp.PostController`. It takes a queryable variable, the
`conn`, and the `params` as arguments.

This sets up a key/value queryable API for the `Post` model. Any
combination of fields on the model can be queried against. For example,
requesting `[GET] /posts?foo=bar&baz=qux` could create the query:

```sql
SELECT p0."foo", p0."baz" FROM posts as p0 WHERE (p0."foo" = $1) AND (p0."baz" = $1);
```

`$1` and `$2` will get the values of `"bar"` and `"qux"`,

### Security

By default, Inquisitor is an opt-in library. It will not provide any
querying access to any key/value pair. The params list will be iterated
over and a no-op function is called on each element. You must add custom
query handlers that have a higher matching order on a case by case
basis.

If you'd like to add a catch-all for any key/value pair you can override
the default:

```elixir
def build_query(query, attr, value, _conn) do
Ecto.Query.where(query, [r], field(r, ^String.to_existing_atom(attr)) == ^value)
end
```

However, this is not recommended. Instead you should create a
`@whitelist` module attribute that contains all of they keys you
wish to allow access to:

```elixir
@whitelist ["title", "bio"]

def build_query(query, attr, value, _conn) when attr in @whitelist do
Ecto.Query.where(query, [r], field(r, ^String.to_existing_atom(attr)) == ^value)
end
```

This will handle matching keys in the whitelist and all unmatched keys
will fall back to the pass-through without affecting the query.

### Adding custom query handlers

Use `build_query/4` to add key/value pair handlers:

```elixir
defmodule MyApp.PostsController do
use Inquisitor

def index(conn, params) do
posts =
App.Post
|> build_query(params)
|> Repo.all()

json(conn, posts)
end

def build_query(query, "inserted_at", date, _conn) do
Ecto.Query.where(query, [p], p.inserted_at >= ^date)
end
end
```

### Handing fields that don't exist on the model

The keys you query against don't need to exist on the model. Revisiting
the date example, let's say we want to find all posts inserted for a
given month and year:

```elixir
def build_query(query, attr, value, _conn) when attr == "month" or attr == "year" do
Ecto.Query.where(query, [e], fragment("date_part(?, ?) = ?", ^attr, e.inserted_at, type(^value, :integer)))
end
```

### Usage Outside of Phoenix Controllers

To use inside a module other than a Phoenix Controller, you'll need to import `Ecto.from/1` otherwise you may see an error like `cannot use ^value outside of match clauses`.

Note: we use `warn: false` to suppress an incorrect warning generated by Elixir thinking `from` is unused.

```elixir
defmodule MyApp.PlainModule do
import Ecto.Query, only: [from: 1], warn: false
use Inquisitor
end
```

### Plugins

We collect all Inquisitor plugins that extend its behavior:

* [inquisitor\_jsonapi](https://github.com/dockyard/inquisitor_jsonapi) - implements query handling according to the JSON API spec

## Authors

* [Brian Cardarella](http://twitter.com/bcardarella)

[We are very thankful for the many contributors](https://github.com/dockyard/inquisitor/graphs/contributors).

## Versioning

This library follows [Semantic Versioning](http://semver.org)

## Want to help?

Please do! We are always looking to improve this library. Please see our
[Contribution Guidelines](https://github.com/dockyard/inquisitor/blob/master/CONTRIBUTING.md)
on how to properly submit issues and pull requests.

## Legal

[DockYard](http://dockyard.com/), Inc. © 2016

[@dockyard](http://twitter.com/dockyard)

[Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)