Skip to content

Commit

Permalink
fix: remove delegate data layer
Browse files Browse the repository at this point in the history
The delegation data layer was the wrong tactic. We should model
shared behavior as composition, not inheritance (which is essentially
what the delegation data layer turned into)
  • Loading branch information
zachdaniel committed Sep 6, 2020
1 parent c75ae78 commit 64c3c50
Show file tree
Hide file tree
Showing 6 changed files with 7 additions and 746 deletions.
3 changes: 0 additions & 3 deletions .formatter.exs
Expand Up @@ -7,8 +7,6 @@ locals_without_parens = [
argument: 3,
attribute: 2,
attribute: 3,
authorize?: 1,
base_filter: 1,
belongs_to: 2,
belongs_to: 3,
calculate: 2,
Expand Down Expand Up @@ -57,7 +55,6 @@ locals_without_parens = [
source_field_on_join_table: 1,
table: 1,
through: 1,
to: 1,
type: 1,
update: 1,
update: 2,
Expand Down
48 changes: 6 additions & 42 deletions documentation/topics/contexts_and_domains.md
Expand Up @@ -4,47 +4,11 @@ It is suggested that you read a bit on Domain Driven Design before proceeding. I

In order to support domain driven design, Ash supports defining multiple APIs, each with their own set of resources. It is possible to share a resource between APIs, but this gets untenable very quickly because any resources related to the shared resource must _both_ appear in each API.

To help solve for this you can use the `Ash.DataLayer.Delegate` data layer, which allows you to map a resource from one API(context) to another. A common example used with DDD is the "user" object. In each context, a user may more rightly be called something else. Perhaps there is a portion of your system used for administration, in which context the user will always be an "administrator". This "administrator" has different fields available,
and different relationships. To represent this in Ash, you may have an "administration api".
An experimental "Delegation" data layer was added to allow you to use other resources in other APIs as the data layer for a resource, but it created a significant amount of complexity in determining data layer behavior. Instead, simply use the same data layer and configuration in both resources.

When following this approach, it is advised to use the same file structure that phoenix uses, with the addition of a `resources` folder. For this example, we have
Things missing to make this work well:

- lib/my_app/administration/resources/administrator.ex -> `MyApp.Administration.Administrator`
- lib/my_app/administration/api.ex -> `MyApp.Administration.Api`
- lib/my_app/accounts/resources/user.ex -> `MyApp.Accounts.User` (not included in the example)
- lib/my_app/accounts/api.ex -> `MyApp.Accounts.Api` (not included in the example)

```elixir
# lib/my_app/administration/api.ex

defmodule MyApp.Administration.Api do
use Ash.Api

resources do
resource MyApp.Administration.Administrator
end
end

# in lib/my_app/administration/resources/administrator.ex

defmodule MyApp.Administration.Administrator do
use Ash.Resource,
data_layer: Ash.DataLayer.Delegate

delegate do
# This resource will be backed by calls to the other API and resource
to {MyApp.Accounts.Api, MyApp.Accounts.User}
# When querying this resource, we include a filter by default on all calls
# This lets us say `MyApp.Administration.Api.read(MyApp.Administration.Administrator)` to easily get
# all adminstrators
base_filter [admin: true]
end

# Define attributes/relationships as usual, using a subset (or all of) the delegated resource's attributes
...
end
```

Now we can add other resources and actions to our administration API, and they can use this more specific/appropriate variation of a user.

More will be coming on the topic of Domain Driven Design with Ash. Many features that will power it have yet to be written.
- Define the ecto schema as a separate module (prerequisite for hidden attributes)
- "hidden" attributes - attributes that are defined on the schema but not the ash struct
- ability to filter on hidden fields in certain places (haven't determined where this needs to happen)
- ability to add a "base_filter" that can leverage hidden attributes

0 comments on commit 64c3c50

Please sign in to comment.