README.md

# Ecto Schema Store

This library is used to create customizable data stores for individual ecto schemas.

With the following schema:

```elixir
defmodule Person do
  use EctoTest.Web, :model

  schema "people" do
    field :name, :string
    field :email, :string

    timestamps
  end

  def changeset(model, params) do
    model
    |> cast(params, [:name, :email])
  end
end
```

You can create a store with the following:

```elixir
defmodule PersonStore do
  use EctoSchemaStore, schema: Person, repo: MyApp.Repo
end
```

## Querying ##

The following functions are provided in a store for retrieving data.

* `all`         - Fetch all records
* `one`         - Return a single record

Sample Queries:

```elixir
# Get all records in a table.
PersonStore.all

# Get all records fields that match the provided value.
PersonStore.all %{name: "Bob"}
PersonStore.all %{name: "Bob", email: "bob@nowhere.test"}

# Return a single record.
PersonStore.one %{name: "Bob"}

# Return a specific record by id.
PersonStore.one 12
```

## Editing ##

The following functions are provided in a store for editing data.

* `insert`       - Insert a record based upon supplied parameters map.
* `insert!`      - Same as `insert` but throws an error instead of returning a tuple.
* `update`       - Update a record based upon supplied parameters map.
* `update!`      - Same as `update` but throws an error instead of returning a tuple.
* `delete`       - Delete a record.
* `delete!`      - Same as `delete` but throws an error instead of returning a tuple.

Sample Usage:

```elixir
bob = PersonStore.insert! %{name: "Bob", email: "bob@nowhere.test"}
bob = PersonStore.update! bob, %{email: "bob2@nowhere.test"}
PersonStore.delete bob

# Updates/deletes can also occur by id.
PersonStore.update! 12, %{email: "bob2@nowhere.test"}
PersonStore.delete 12
```

## Changesets ##

The `insert` and `update` functions by default use a changeset on the provided schema name `:changeset` for inserting and updating.
This can be overridden and a specific changeset name provided.

```elixir
bob = PersonStore.insert! %{name: "Bob", email: "bob@nowhere.test"}, :insert_changeset
bob = PersonStore.update! bob, %{email: "bob2@nowhere.test"}, :update_changeset
bob = PersonStore.update! bob, %{email: "bob2@nowhere.test"}, :my_other_custom_changeset
``` 

## References ##

The internal references to the schema and the provided Ecto Repo are provided as convience functions.

* `schema`         - returns the schema reference used internally by the store.
* `repo`           - returns the Ecto Repo reference used internally by the store.

## Custom Actions ##

Since a store is just an ordinary module, you can add your actions and build off private APIs to the store. For convience
`Ecto.Query` is already fully imported into the module.

A store is provided the following custom internal API:

* `build_query`       - Builds a `Ecto.Query` struct based upon the map params input.

```elixir
defmodule PersonStore do
  use EctoSchemaStore, schema: Person, repo: MyApp.Repo

  def get_all_ordered_by_name do
    build_query
    |> order_by([:name])
    |> all
  end

  def find_by_email(email) do
    %{email: email}
    |> build_query
    |> order_by([:name])
    |> all
  end

  def get_all_ordered_by_name_using_ecto_directly do
    query = from p in schema,
            order_by: [p.name]
    
    repo.all query
  end
end
```

## Schema Field Aliases ##

Sometimes field names get changed or the developer wishes to have an alias that represents another field.
These work for both querying and editing schema models.

```elixir
defmodule PersonStore do
  use EctoSchemaStore, schema: Person, repo: MyApp.Repo

  alias_fields email_address: :email
end

PersonStore.all %{email_address: "bob@nowhere.test"}
PersonStore.update! 12, %{email_address: "bob@nowhere.test"}
```