# `Patterns.Queryable.DSL`
[🔗](https://github.com/minnasoft/patterns/blob/v0.0.1/lib/patterns/queryable/dsl.ex#L1)

Binding-aware query helpers for `Patterns.Queryable`.

This module extends Ecto query composition with two small pieces:

* `from/2`, which supports `binding/1` and `binding/2` source patterns.
* Binding inspection helpers for resolving named bindings to indexes and
  schema modules.

Most callers get `from/2` through `use Patterns.Queryable`. The binding
inspection helpers are used by `Patterns.Queryable.Filters` to resolve nested
association filters from the current scoped binding.

# `binding_index`

Returns the query binding index for a named binding.

    binding_index(from(post in Blog.Post, as: :post), :post)
    #=> 0

    binding_index(from(post in Blog.Post, as: :self), :self)
    #=> 0

The unnamed root binding is index `0`, but it is not addressable as `:self`
unless the query was explicitly created with `as: :self`.

    binding_index(from(post in Blog.Post), :self)
    # raises ArgumentError, "query binding :self does not exist"

    binding_index(from(post in Blog.Post), :missing)
    # raises ArgumentError, "query binding :missing does not exist"

# `binding_schema`

Returns the Ecto schema module for the current scoped query binding.

    binding_schema(from post in Blog.Post)
    #=> Blog.Post

Raises `ArgumentError` when the current binding does not resolve to an Ecto
schema source.

    binding_schema(from post in "posts")
    # raises ArgumentError, "root query binding must be an Ecto schema source"

# `binding_schema`

Returns the Ecto schema module for a named query binding or binding index.

    binding_schema(
      from(post in Blog.Post, join: comment in assoc(post, :comments), as: :comments),
      :comments
    )
    #=> Blog.Comment

    binding_schema(
      from(post in Blog.Post, join: comment in assoc(post, :comments), as: :comments),
      1
    )
    #=> Blog.Comment

Raises `ArgumentError` when the binding does not exist or does not resolve to
an Ecto schema source.

    binding_schema(from(post in Blog.Post), :missing)
    # raises ArgumentError, "query binding :missing does not exist"

    binding_schema(from(post in Blog.Post), 2)
    # raises ArgumentError, "query binding at index 2 does not exist"

# `from`
*macro* 

Extends `Ecto.Query.from/2` with binding-aware query source patterns.

This macro otherwise delegates to Ecto's `from` DSL unchanged. It exists so
modules using `Patterns.Queryable` can write queries against either the root
binding or a binding supplied by surrounding query composition.

Use `binding/1` to target the current scoped binding, falling back to the root
query binding:

    from binding(entry) in query,
      where: entry.slug == ^slug

Use `binding/2` to target an explicit named binding:

    from binding(:references, reference) in query,
      where: reference.target_slug == ^slug

---

*Consult [api-reference.md](api-reference.md) for complete listing*
