Skip to content

Commit

Permalink
improvement: various managed relationship improvements
Browse files Browse the repository at this point in the history
fix: rename `context` -> `relationship_context` to avoid conflict
feat: `on_no_match: :match` supported for to_one rels
  • Loading branch information
zachdaniel committed May 14, 2021
1 parent d2a51a0 commit 574f6f5
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ locals_without_parens = [
change: 1,
change: 2,
constraints: 1,
context: 1,
count: 2,
count: 3,
create: 1,
Expand Down Expand Up @@ -86,6 +85,7 @@ locals_without_parens = [
read: 2,
read_action: 1,
reject: 1,
relationship_context: 1,
require_attributes: 1,
required?: 1,
resource: 1,
Expand Down
29 changes: 23 additions & 6 deletions lib/ash/actions/managed_relationships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ defmodule Ash.Actions.ManagedRelationships do
other
end

case find_match(List.wrap(current_value), input, pkeys, relationship) do
case find_match(
List.wrap(current_value),
input,
pkeys,
relationship,
opts[:on_no_match] == :match
) do
nil ->
case opts[:on_lookup] do
:ignore ->
Expand Down Expand Up @@ -215,7 +221,7 @@ defmodule Ash.Actions.ManagedRelationships do
opts
) do
case opts[:on_no_match] do
:ignore ->
ignore when ignore in [:ignore, :match] ->
{:cont, {changeset, instructions}}

:error ->
Expand Down Expand Up @@ -515,7 +521,14 @@ defmodule Ash.Actions.ManagedRelationships do
index,
opts
) do
match = find_match(List.wrap(original_value), input, pkeys, relationship)
match =
find_match(
List.wrap(original_value),
input,
pkeys,
relationship,
opts[:on_no_match] == :match
)

if is_nil(match) || opts[:on_match] == :no_match do
case handle_create(
Expand Down Expand Up @@ -1045,13 +1058,17 @@ defmodule Ash.Actions.ManagedRelationships do
end
end

defp find_match(current_value, input, pkeys, relationship \\ nil)
defp find_match(current_value, input, pkeys, relationship \\ nil, force_has_one? \\ false)

defp find_match(%Ash.NotLoaded{}, _input, _pkeys, _relationship) do
defp find_match(%Ash.NotLoaded{}, _input, _pkeys, _relationship, _force_has_one?) do
nil
end

defp find_match(current_value, input, pkeys, relationship) do
defp find_match([match], _input, _pkeys, %{cardinality: :one}, true) do
match
end

defp find_match(current_value, input, pkeys, relationship, _force_has_one?) do
Enum.find(current_value, fn current_value ->
Enum.any?(pkeys, fn pkey ->
matches?(current_value, input, pkey, relationship)
Expand Down
1 change: 1 addition & 0 deletions lib/ash/changeset/changeset.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ defmodule Ash.Changeset do
doc: """
instructions for handling records where no matching record existed in the relationship
* `:ignore`(default) - those inputs are ignored
* `:match` - For "has_one" and "belongs_to" only, any input is treated as a match for an existing value. For has_many and many_to_many, this is the same as :ignore.
* `:create` - the records are created using the destination's primary create action
* `{:create, :action_name}` - the records are created using the specified action on the destination resource
* `{:create, :action_name, :join_table_action_name, [:list, :of, :join_table, :params]}` - Same as `{:create, :action_name}` but takes
Expand Down
3 changes: 3 additions & 0 deletions lib/ash/changeset/managed_relationship_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ defmodule Ash.Changeset.ManagedRelationshipHelpers do
value when value in [:ignore, :error] ->
nil

:match ->
on_match_destination_actions(opts, relationship)

:create ->
all(destination(primary_action_name(relationship.destination, :create)))

Expand Down
1 change: 1 addition & 0 deletions lib/ash/dsl/entity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ defmodule Ash.Dsl.Entity do
with {:ok, opts} <-
Ash.OptionsHelpers.validate(Keyword.merge(opts || [], before_validate_auto), schema),
opts <- Keyword.merge(opts, after_validate_auto),
opts <- Enum.map(opts, fn {key, value} -> {schema[key][:as] || key, value} end),
built <- struct(target, opts),
built <- struct(built, nested_entities),
{:ok, built} <-
Expand Down
2 changes: 1 addition & 1 deletion lib/ash/options_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ defmodule Ash.OptionsHelpers do
opts
end

{key, Keyword.delete(new_opts, :hide)}
{key, Keyword.drop(new_opts, [:hide, :as])}
end)
end

Expand Down
3 changes: 2 additions & 1 deletion lib/ash/resource/relationships/shared_options.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ defmodule Ash.Resource.Relationships.SharedOptions do
type: :string,
doc: "An optional description for the relationship"
],
context: [
relationship_context: [
type: :any,
as: :context,
doc: """
Context to be set on any queries or changesets generated for this relationship.
Expand Down

0 comments on commit 574f6f5

Please sign in to comment.