-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bdab2ca
Showing
37 changed files
with
1,464 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
### Assoc | ||
|
||
# Database | ||
|
||
export ASSOC_TEST_POSTGRES_USER=postgres | ||
export ASSOC_TEST_POSTGRES_PASS=postgres | ||
export ASSOC_TEST_POSTGRES_HOST=localhost | ||
export ASSOC_TEST_POSTGRES_DB=assoc_test | ||
|
||
### Elixir Version | ||
|
||
export ELIXIR_VERSION="1.8.1" | ||
export PATH="$HOME/.kiex/elixirs/elixir-1.8.1/bin:$PATH" | ||
export MIX_ARCHIVES="$HOME/.kiex/mix/archives/elixir-1.8.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
### Assoc | ||
|
||
# Database | ||
|
||
export ASSOC_TEST_POSTGRES_USER=postgres | ||
export ASSOC_TEST_POSTGRES_PASS= | ||
export ASSOC_TEST_POSTGRES_HOST=localhost | ||
export ASSOC_TEST_POSTGRES_DB=assoc_test | ||
|
||
### Elixir Version | ||
|
||
export ELIXIR_VERSION="1.8.1" | ||
export PATH="$HOME/.kiex/elixirs/elixir-1.8.1/bin:$PATH" | ||
export MIX_ARCHIVES="$HOME/.kiex/mix/archives/elixir-1.8.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# The directory Mix will write compiled artifacts to. | ||
/_build/ | ||
|
||
# If you run "mix test --cover", coverage assets end up here. | ||
/cover/ | ||
|
||
# The directory Mix downloads your dependencies sources to. | ||
/deps/ | ||
|
||
# Where 3rd-party dependencies like ExDoc output generated docs. | ||
/doc/ | ||
|
||
# Ignore .fetch files in case you like to edit your project deps locally. | ||
/.fetch | ||
|
||
# If the VM crashes, it generates a dump, let's ignore it too. | ||
erl_crash.dump | ||
|
||
# Also ignore archive artifacts (built via "mix archive.build"). | ||
*.ez | ||
|
||
# Ignore package tarball (built via "mix hex.build"). | ||
assoc-*.tar | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Changelog | ||
|
||
## [v0.1.0] - 2019-01-30 | ||
|
||
- Initial Release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Assoc | ||
|
||
> An easy way to manage `many_to_many`, `has_many` and `belongs_to` Ecto associations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
use Mix.Config | ||
|
||
import_config "./#{Mix.env()}.exs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
use Mix.Config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
use Mix.Config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use Mix.Config | ||
|
||
# Set the log level | ||
# | ||
# The order from most information to least: | ||
# | ||
# :debug | ||
# :info | ||
# :warn | ||
# | ||
config :logger, level: :info | ||
|
||
config :assoc, | ||
ecto_repos: [Assoc.Test.Repo] | ||
|
||
config :assoc, Assoc.Test.Repo, | ||
username: System.get_env("ASSOC_TEST_POSTGRES_USER"), | ||
password: System.get_env("ASSOC_TEST_POSTGRES_PASS"), | ||
database: System.get_env("ASSOC_TEST_POSTGRES_DB"), | ||
hostname: System.get_env("ASSOC_TEST_POSTGRES_HOST"), | ||
pool: Ecto.Adapters.SQL.Sandbox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
defmodule Assoc do | ||
@moduledoc """ | ||
""" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
defmodule Assoc.Schema do | ||
@moduledoc """ | ||
## Usage | ||
``` | ||
defmodule MyApp.User do | ||
use MyApp.Schema | ||
use Assoc.Schema, repo: MyApp.Repo | ||
schema "users" do | ||
field :email, :string | ||
field :name, :string | ||
has_many :user_roles, MyApp.UserRole, on_delete: :delete_all, on_replace: :delete | ||
timestamps() | ||
end | ||
def updatable_associations, do: [ | ||
user_roles: MyApp.UserRole | ||
] | ||
def changeset(struct, params \\ %{}) do | ||
struct | ||
|> cast(params, [:email, :name]) | ||
|> validate_required([:email]) | ||
end | ||
end | ||
``` | ||
Key points: | ||
- The `use Assoc.Schema` line should come after `use MyApp.Schema`. | ||
- Pass the app's Repo into `use Assoc.Schema, repo: MyApp.Repo` | ||
- Define a `updatable_associations` function. For each updatable association: | ||
- The `key` should be the association name | ||
- The `value` should be the association schema module | ||
- The standard `changeset` function does not change. | ||
- Include all the standard code for updating struct values (e.g. name, email) in `changeset` | ||
- The library will create and use a separate `associations_changeset` to manage the associations | ||
""" | ||
|
||
@callback updatable_associations :: List.t | ||
|
||
defmacro __using__(repo: repo) do | ||
quote do | ||
@doc """ | ||
Preload all schema associations. | ||
## Usage | ||
``` | ||
MyApp.User.preload_all(user) | ||
``` | ||
## Implementation | ||
Builds a list of keys with `Ecto.Association.NotLoaded` values. Then | ||
feeds the list into `Repo.preload`. | ||
""" | ||
def preload_all(struct) do | ||
keys = struct | ||
|> Map.from_struct | ||
|> Enum.reduce([], fn ({key, value}, acc) -> | ||
case value do | ||
%Ecto.Association.NotLoaded{} -> [key|acc] | ||
_ -> acc | ||
end | ||
end) | ||
|
||
unquote(repo).preload(struct, keys) | ||
end | ||
|
||
@doc """ | ||
Update associations defined in `updatable_associations/0` callback. | ||
""" | ||
def associations_changeset(struct, params \\ %{}) do | ||
struct = preload_associations(struct, updatable_associations()) | ||
params = include_existing_associations(struct, params) | ||
|
||
struct | ||
|> cast(params, []) | ||
|> put_associations(updatable_associations(), params) | ||
end | ||
|
||
@doc """ | ||
Preload selected schema associations. | ||
""" | ||
def preload_associations(struct, associations) do | ||
associations = case Keyword.keyword?(associations) do | ||
true -> Keyword.keys(associations) | ||
false -> associations | ||
end | ||
|
||
unquote(repo).preload(struct, associations) | ||
end | ||
|
||
# Include existing associations in params by merging params into preload struct | ||
defp include_existing_associations(struct, params) do | ||
struct | ||
|> Map.from_struct | ||
|> Map.merge(params) | ||
end | ||
|
||
# Dynamically adds `put_assoc` calls to changeset | ||
defp put_associations(changeset, associations, params) do | ||
Enum.reduce(associations, changeset, fn ({key, _}, acc) -> | ||
value = params | ||
|> Assoc.Util.keys_to_atoms() | ||
|> Map.get(key, :omitted) | ||
|
||
case value do | ||
:omitted -> acc | ||
value -> put_assoc(acc, key, value) | ||
end | ||
end) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.