improvement: make long-awaited DSL name changes

This commit is contained in:
Zach Daniel 2022-08-15 14:00:02 -04:00
parent 44adc9a1b8
commit 6c79519b6c
53 changed files with 456 additions and 432 deletions

View file

@ -18,6 +18,7 @@ locals_without_parens = [
attribute: 1,
attribute: 2,
attribute: 3,
attribute_type: 1,
attribute_writable?: 1,
authorize: 1,
authorize_if: 1,
@ -55,11 +56,11 @@ locals_without_parens = [
defaults: 1,
define: 1,
define: 2,
define_field?: 1,
define_attribute?: 1,
define_for: 1,
description: 1,
destination_field: 1,
destination_field_on_join_table: 1,
destination_attribute: 1,
destination_attribute_on_join_resource: 1,
destroy: 1,
destroy: 2,
destroy: 3,
@ -70,9 +71,7 @@ locals_without_parens = [
entry: 2,
error_handler: 1,
event: 1,
expensive?: 1,
field: 1,
field_type: 1,
filter: 1,
filterable?: 1,
first: 3,
@ -113,7 +112,7 @@ locals_without_parens = [
modify_query: 1,
module: 1,
name: 1,
no_fields?: 1,
no_attributes?: 1,
not_found_message: 1,
on: 1,
only_when_valid?: 1,
@ -153,8 +152,8 @@ locals_without_parens = [
soft?: 1,
sort: 1,
source: 1,
source_field: 1,
source_field_on_join_table: 1,
source_attribute: 1,
source_attribute_on_join_resource: 1,
strategy: 1,
sum: 3,
sum: 4,
@ -180,7 +179,7 @@ locals_without_parens = [
uuid_primary_key: 2,
validate: 1,
validate: 2,
validate_destination_field?: 1,
validate_destination_attribute?: 1,
violation_message: 1,
wait_for: 1,
warn_on_empty?: 1,

View file

@ -456,7 +456,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
* use new `no_depend_modules` everywhere
* add `no_fields?` relationships
* add `no_attributes?` relationships
* add manual read actions
@ -2082,7 +2082,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
### Improvements:
* add `validate_destination_field?`
* add `validate_destination_attribute?`
* add builtin `select` change
@ -2813,7 +2813,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
### Bug Fixes:
* set `source_field` when replacing `belongs_to` relationship
* set `source_attribute` when replacing `belongs_to` relationship
* don't consider `false` as absent value
@ -2913,7 +2913,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
### Improvements:
* derive has_one destination_field
* derive has_one destination_attribute
* finalize code API logic
@ -3077,7 +3077,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
* many compile time fixes via code splitting
* Guess destination_field for has many relationships (#187)
* Guess destination_attribute for has many relationships (#187)
* Implement string length validation (#183)
@ -3090,7 +3090,7 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline
* many compile time fixes via code splitting
* Guess destination_field for has many relationships (#187)
* Guess destination_attribute for has many relationships (#187)
* Implement string length validation (#183)

View file

@ -52,7 +52,7 @@ defmodule Ash.Actions.Load do
else
related_query
end
|> Ash.Query.ensure_selected(relationship.destination_field)
|> Ash.Query.ensure_selected(relationship.destination_attribute)
related_query =
if relationship.cardinality == :one do
@ -75,10 +75,10 @@ defmodule Ash.Actions.Load do
)
query =
if Map.get(relationship, :no_fields?) do
if Map.get(relationship, :no_attributes?) do
query
else
Ash.Query.ensure_selected(query, relationship.source_field)
Ash.Query.ensure_selected(query, relationship.source_attribute)
end
{
@ -139,7 +139,7 @@ defmodule Ash.Actions.Load do
data
end
defp attach_to_many_loads(value, %{name: name, no_fields?: true}, data, lead_path) do
defp attach_to_many_loads(value, %{name: name, no_attributes?: true}, data, lead_path) do
map_or_update(data, lead_path, fn record ->
Map.put(record, name, List.wrap(value))
end)
@ -154,16 +154,16 @@ defmodule Ash.Actions.Load do
end
defp attach_to_many_loads(value, last_relationship, data, lead_path) do
values = Enum.group_by(value, &Map.get(&1, last_relationship.destination_field))
values = Enum.group_by(value, &Map.get(&1, last_relationship.destination_attribute))
map_or_update(data, lead_path, fn record ->
source_key = Map.get(record, last_relationship.source_field)
source_key = Map.get(record, last_relationship.source_attribute)
related_records = Map.get(values, source_key, [])
Map.put(record, last_relationship.name, related_records)
end)
end
defp attach_to_one_loads(value, %{name: name, no_fields?: true}, data, lead_path) do
defp attach_to_one_loads(value, %{name: name, no_attributes?: true}, data, lead_path) do
map_or_update(data, lead_path, fn record ->
Map.put(record, name, value |> List.wrap() |> Enum.at(0))
end)
@ -182,11 +182,11 @@ defmodule Ash.Actions.Load do
value
|> Enum.reverse()
|> Enum.into(%{}, fn item ->
{Map.get(item, last_relationship.destination_field), item}
{Map.get(item, last_relationship.destination_attribute), item}
end)
map_or_update(data, lead_path, fn record ->
source_key = Map.get(record, last_relationship.source_field)
source_key = Map.get(record, last_relationship.source_attribute)
related_record = Map.get(values, source_key)
Map.put(record, last_relationship.name, related_record)
end)
@ -201,20 +201,20 @@ defmodule Ash.Actions.Load do
|> Map.get(:data, [])
map_or_update(data, lead_path, fn record ->
source_value = Map.get(record, last_relationship.source_field)
source_value = Map.get(record, last_relationship.source_attribute)
join_values =
join_data
|> Enum.filter(fn join_row ->
Map.get(join_row, last_relationship.source_field_on_join_table) ==
Map.get(join_row, last_relationship.source_attribute_on_join_resource) ==
source_value
end)
|> Enum.map(&Map.get(&1, last_relationship.destination_field_on_join_table))
|> Enum.map(&Map.get(&1, last_relationship.destination_attribute_on_join_resource))
related_records =
value
|> Enum.filter(fn value ->
destination_value = Map.get(value, last_relationship.destination_field)
destination_value = Map.get(value, last_relationship.destination_attribute)
destination_value in join_values
end)
@ -742,10 +742,10 @@ defmodule Ash.Actions.Load do
end
|> List.wrap()
|> Enum.map(fn related ->
Map.get(related, relationship.destination_field)
Map.get(related, relationship.destination_attribute)
end)
filter = [{relationship.destination_field_on_join_table, [{:in, ids}]}]
filter = [{relationship.destination_attribute_on_join_resource, [{:in, ids}]}]
Ash.Query.filter(query, ^filter)
end
@ -841,10 +841,10 @@ defmodule Ash.Actions.Load do
lateral_join_source: {
source_data,
[
{source_query, relationship.source_field,
relationship.source_field_on_join_table, relationship},
{relationship.through, relationship.destination_field_on_join_table,
relationship.destination_field, join_relationship}
{source_query, relationship.source_attribute,
relationship.source_attribute_on_join_resource, relationship},
{relationship.through, relationship.destination_attribute_on_join_resource,
relationship.destination_attribute, join_relationship}
]
}
}
@ -862,8 +862,8 @@ defmodule Ash.Actions.Load do
lateral_join_source:
{source_data,
[
{source_query, relationship.source_field, relationship.destination_field,
relationship}
{source_query, relationship.source_attribute,
relationship.destination_attribute, relationship}
]}
}
})
@ -908,7 +908,7 @@ defmodule Ash.Actions.Load do
new_results =
results
|> Enum.group_by(fn record ->
Map.get(record, relationship.destination_field)
Map.get(record, relationship.destination_attribute)
end)
|> Enum.flat_map(fn {_, group} ->
offset_records = Enum.drop(group, offset || 0)
@ -999,7 +999,7 @@ defmodule Ash.Actions.Load do
relationship,
related_query
) do
if Map.get(relationship, :no_fields?) do
if Map.get(relationship, :no_attributes?) do
relationship.destination
|> Ash.Query.new(related_query.api)
else
@ -1010,14 +1010,14 @@ defmodule Ash.Actions.Load do
end
defp true_load_query(relationship, query, data, path, request_path) do
{source_field, path} =
{source_attribute, path} =
if relationship.type == :many_to_many do
join_relationship = join_relationship(relationship)
{relationship.destination_field_on_join_table,
{relationship.destination_attribute_on_join_resource,
join_relationship_path(path, join_relationship) |> Enum.map(& &1.name)}
else
{relationship.source_field, path |> Enum.reverse() |> Enum.map(& &1.name)}
{relationship.source_attribute, path |> Enum.reverse() |> Enum.map(& &1.name)}
end
source_data =
@ -1042,18 +1042,18 @@ defmodule Ash.Actions.Load do
:nothing
_ ->
get_query(query, relationship, source_data, source_field)
get_query(query, relationship, source_data, source_attribute)
end
end
defp get_query(query, relationship, source_data, source_field) do
defp get_query(query, relationship, source_data, source_attribute) do
{offset, limit} = offset_and_limit(query)
cond do
lateral_join?(query, relationship, source_data) ->
{:ok, Ash.Query.unset(query, :load)}
Map.get(relationship, :no_fields?) ->
Map.get(relationship, :no_attributes?) ->
{:ok, query}
true ->
@ -1076,7 +1076,7 @@ defmodule Ash.Actions.Load do
ids =
Enum.flat_map(related_data, fn data ->
data
|> Map.get(source_field)
|> Map.get(source_attribute)
|> List.wrap()
end)
@ -1091,7 +1091,7 @@ defmodule Ash.Actions.Load do
new_query =
query
|> Ash.Query.filter(^[{relationship.destination_field, filter_value}])
|> Ash.Query.filter(^[{relationship.destination_attribute, filter_value}])
|> Ash.Query.unset(:load)
{:ok, new_query}
@ -1177,12 +1177,12 @@ defmodule Ash.Actions.Load do
defp reverse_relationship?(rel, destination_rel) do
rel.source == destination_rel.destination &&
rel.destination == destination_rel.source &&
rel.source_field == destination_rel.destination_field &&
rel.destination_field == destination_rel.source_field &&
Map.fetch(rel, :source_field_on_join_table) ==
Map.fetch(destination_rel, :destination_field_on_join_table) &&
Map.fetch(rel, :destination_field_on_join_table) ==
Map.fetch(destination_rel, :source_field_on_join_table) &&
rel.source_attribute == destination_rel.destination_attribute &&
rel.destination_attribute == destination_rel.source_attribute &&
Map.fetch(rel, :source_attribute_on_join_resource) ==
Map.fetch(destination_rel, :destination_attribute_on_join_resource) &&
Map.fetch(rel, :destination_attribute_on_join_resource) ==
Map.fetch(destination_rel, :source_attribute_on_join_resource) &&
is_nil(destination_rel.context) &&
is_nil(rel.context)
end

View file

@ -103,7 +103,7 @@ defmodule Ash.Actions.ManagedRelationships do
changeset =
if input in [nil, []] && opts[:on_missing] != :ignore do
changeset
|> maybe_force_change_attribute(relationship, :source_field, nil)
|> maybe_force_change_attribute(relationship, :source_attribute, nil)
|> Ash.Changeset.after_action(fn _changeset, result ->
{:ok, Map.put(result, relationship.name, nil)}
end)
@ -176,8 +176,8 @@ defmodule Ash.Actions.ManagedRelationships do
})
|> maybe_force_change_attribute(
relationship,
:source_field,
Map.get(input, relationship.destination_field)
:source_attribute,
Map.get(input, relationship.destination_attribute)
)
{:cont, {changeset, instructions}}
@ -237,8 +237,8 @@ defmodule Ash.Actions.ManagedRelationships do
})
|> maybe_force_change_attribute(
relationship,
:source_field,
Map.get(found, relationship.destination_field)
:source_attribute,
Map.get(found, relationship.destination_attribute)
)
{:cont, {changeset, instructions}}
@ -259,7 +259,7 @@ defmodule Ash.Actions.ManagedRelationships do
maybe_force_change_attribute(
changeset,
relationship,
:source_field,
:source_attribute,
nil
)
@ -315,7 +315,7 @@ defmodule Ash.Actions.ManagedRelationships do
relationship.api || changeset.api
end
defp maybe_force_change_attribute(changeset, %{no_fields?: true}, _, _), do: changeset
defp maybe_force_change_attribute(changeset, %{no_attributes?: true}, _, _), do: changeset
defp maybe_force_change_attribute(changeset, relationship, key, value) do
Ash.Changeset.force_change_attribute(
@ -349,7 +349,7 @@ defmodule Ash.Actions.ManagedRelationships do
|> Enum.reduce({changeset, instructions}, fn required_relationship,
{changeset, instructions} ->
changeset =
case Ash.Changeset.get_attribute(changeset, required_relationship.source_field) do
case Ash.Changeset.get_attribute(changeset, required_relationship.source_attribute) do
nil ->
Ash.Changeset.add_error(
changeset,
@ -462,8 +462,8 @@ defmodule Ash.Actions.ManagedRelationships do
})
|> maybe_force_change_attribute(
relationship,
:source_field,
Map.get(created, relationship.destination_field)
:source_attribute,
Map.get(created, relationship.destination_attribute)
)
{:cont,
@ -944,13 +944,13 @@ defmodule Ash.Actions.ManagedRelationships do
)
|> maybe_force_change_attribute(
relationship,
:source_field_on_join_table,
Map.get(record, relationship.source_field)
:source_attribute_on_join_resource,
Map.get(record, relationship.source_attribute)
)
|> maybe_force_change_attribute(
relationship,
:destination_field_on_join_table,
Map.get(found, relationship.destination_field)
:destination_attribute_on_join_resource,
Map.get(found, relationship.destination_attribute)
)
|> Ash.Changeset.set_context(join_relationship.context)
|> Ash.Changeset.set_tenant(changeset.tenant)
@ -1006,8 +1006,8 @@ defmodule Ash.Actions.ManagedRelationships do
)
|> maybe_force_change_attribute(
relationship,
:destination_field,
Map.get(record, relationship.source_field)
:destination_attribute,
Map.get(record, relationship.source_attribute)
)
|> Ash.Changeset.set_context(relationship.context)
|> Ash.Changeset.set_tenant(changeset.tenant)
@ -1066,8 +1066,8 @@ defmodule Ash.Actions.ManagedRelationships do
)
|> maybe_force_change_attribute(
relationship,
:destination_field,
Map.get(record, relationship.source_field)
:destination_attribute,
Map.get(record, relationship.source_attribute)
)
|> Ash.Changeset.set_context(relationship.context)
|> Ash.Changeset.set_tenant(changeset.tenant)
@ -1134,13 +1134,13 @@ defmodule Ash.Actions.ManagedRelationships do
)
|> maybe_force_change_attribute(
relationship,
:source_field_on_join_table,
Map.get(record, relationship.source_field)
:source_attribute_on_join_resource,
Map.get(record, relationship.source_attribute)
)
|> maybe_force_change_attribute(
relationship,
:destination_field_on_join_table,
Map.get(created, relationship.destination_field)
:destination_attribute_on_join_resource,
Map.get(created, relationship.destination_attribute)
)
|> Ash.Changeset.set_context(join_relationship.context)
|> Ash.Changeset.set_tenant(changeset.tenant)
@ -1275,7 +1275,7 @@ defmodule Ash.Actions.ManagedRelationships do
{match, regular_params}
end
source_value = Map.get(source_record, relationship.source_field)
source_value = Map.get(source_record, relationship.source_attribute)
match
|> Ash.Changeset.new()
@ -1289,15 +1289,17 @@ defmodule Ash.Actions.ManagedRelationships do
|> api.update(return_notifications?: true)
|> case do
{:ok, updated, update_notifications} ->
destination_value = Map.get(updated, relationship.destination_field)
destination_value = Map.get(updated, relationship.destination_attribute)
join_relationship =
Ash.Resource.Info.relationship(relationship.source, relationship.join_relationship)
relationship.through
|> Ash.Query.filter(ref(^relationship.source_field_on_join_table) == ^source_value)
|> Ash.Query.filter(
ref(^relationship.destination_field_on_join_table) == ^destination_value
ref(^relationship.source_attribute_on_join_resource) == ^source_value
)
|> Ash.Query.filter(
ref(^relationship.destination_attribute_on_join_resource) == ^destination_value
)
|> Ash.Query.set_context(join_relationship.context)
|> Ash.Query.limit(1)
@ -1367,9 +1369,9 @@ defmodule Ash.Actions.ManagedRelationships do
defp matches?(current_value, input, pkey, relationship) do
if relationship && relationship.type in [:has_one, :has_many] &&
relationship.destination_field in pkey do
relationship.destination_attribute in pkey do
Enum.all?(pkey, fn field ->
if field == relationship.destination_field do
if field == relationship.destination_attribute do
if is_struct(input) do
do_matches?(current_value, input, field)
else
@ -1445,16 +1447,18 @@ defmodule Ash.Actions.ManagedRelationships do
{:cont, {:ok, [record | current_value], []}}
{:destroy, action_name, join_action_name} ->
source_value = Map.get(source_record, relationship.source_field)
destination_value = Map.get(record, relationship.destination_field)
source_value = Map.get(source_record, relationship.source_attribute)
destination_value = Map.get(record, relationship.destination_attribute)
join_relationship =
Ash.Resource.Info.relationship(relationship.source, relationship.join_relationship)
relationship.through
|> Ash.Query.filter(ref(^relationship.source_field_on_join_table) == ^source_value)
|> Ash.Query.filter(
ref(^relationship.destination_field_on_join_table) == ^destination_value
ref(^relationship.source_attribute_on_join_resource) == ^source_value
)
|> Ash.Query.filter(
ref(^relationship.destination_attribute_on_join_resource) == ^destination_value
)
|> Ash.Query.limit(1)
|> Ash.Query.set_tenant(changeset.tenant)
@ -1571,15 +1575,17 @@ defmodule Ash.Actions.ManagedRelationships do
action_name =
action_name || Ash.Resource.Info.primary_action(relationship.through, :destroy).name
source_value = Map.get(source_record, relationship.source_field)
destination_value = Map.get(record, relationship.destination_field)
source_value = Map.get(source_record, relationship.source_attribute)
destination_value = Map.get(record, relationship.destination_attribute)
join_relationship =
Ash.Resource.Info.relationship(relationship.source, relationship.join_relationship)
relationship.through
|> Ash.Query.filter(ref(^relationship.source_field_on_join_table) == ^source_value)
|> Ash.Query.filter(ref(^relationship.destination_field_on_join_table) == ^destination_value)
|> Ash.Query.filter(ref(^relationship.source_attribute_on_join_resource) == ^source_value)
|> Ash.Query.filter(
ref(^relationship.destination_attribute_on_join_resource) == ^destination_value
)
|> Ash.Query.limit(1)
|> Ash.Query.set_tenant(tenant)
|> Ash.Query.set_context(join_relationship.context)
@ -1626,7 +1632,7 @@ defmodule Ash.Actions.ManagedRelationships do
authorize?: opts[:authorize?],
actor: actor
)
|> maybe_force_change_attribute(relationship, :destination_field, nil)
|> maybe_force_change_attribute(relationship, :destination_attribute, nil)
|> Ash.Changeset.set_context(relationship.context)
|> Ash.Changeset.set_tenant(tenant)
|> api.update(return_notifications?: true)
@ -1665,12 +1671,14 @@ defmodule Ash.Actions.ManagedRelationships do
action_name =
action_name || Ash.Resource.Info.primary_action(relationship.through, :destroy).name
source_value = Map.get(source_record, relationship.source_field)
destination_value = Map.get(record, relationship.destination_field)
source_value = Map.get(source_record, relationship.source_attribute)
destination_value = Map.get(record, relationship.destination_attribute)
relationship.through
|> Ash.Query.filter(ref(^relationship.source_field_on_join_table) == ^source_value)
|> Ash.Query.filter(ref(^relationship.destination_field_on_join_table) == ^destination_value)
|> Ash.Query.filter(ref(^relationship.source_attribute_on_join_resource) == ^source_value)
|> Ash.Query.filter(
ref(^relationship.destination_attribute_on_join_resource) == ^destination_value
)
|> Ash.Query.limit(1)
|> Ash.Query.set_tenant(tenant)
|> api.read_one(authorize?: opts[:authorize?], actor: actor)

View file

@ -158,13 +158,13 @@ defmodule Ash.Actions.Sort do
{field, {:ok, aggregate.type}}
%Ash.Resource.Aggregate{} = agg ->
field_type =
attribute_type =
if agg.field do
related = Ash.Resource.Info.related(resource, agg.relationship_path)
Ash.Resource.Info.attribute(related, agg.field).type
end
{agg.name, Ash.Query.Aggregate.kind_to_type(agg.kind, field_type)}
{agg.name, Ash.Query.Aggregate.kind_to_type(agg.kind, attribute_type)}
end
case type do

View file

@ -1048,14 +1048,14 @@ defmodule Ash.Changeset do
defp validate(changeset, validation) do
if validation.before_action? do
before_action(changeset, fn changeset ->
if validation.expensive? and not changeset.valid? do
if validation.only_when_valid? and not changeset.valid? do
changeset
else
do_validation(changeset, validation)
end
end)
else
if validation.expensive? and not changeset.valid? do
if validation.only_when_valid? and not changeset.valid? do
changeset
else
do_validation(changeset, validation)
@ -1243,7 +1243,7 @@ defmodule Ash.Changeset do
resource
|> Ash.Resource.Info.relationships()
|> Enum.filter(&(&1.type == :belongs_to))
|> Enum.map(& &1.source_field)
|> Enum.map(& &1.source_attribute)
action =
case action do
@ -1690,9 +1690,9 @@ defmodule Ash.Changeset do
* `:no_match` - ignores the primary key match and follows the on_no_match instructions with these records instead.
* `:unrelate` - the related item is not destroyed, but the data is "unrelated", making this behave like `remove_from_relationship/3`. The action should be:
* many_to_many - the join resource row is destroyed
* has_many - the destination_field (on the related record) is set to `nil`
* has_one - the destination_field (on the related record) is set to `nil`
* belongs_to - the source_field (on this record) is set to `nil`
* has_many - the destination_attribute (on the related record) is set to `nil`
* has_one - the destination_attribute (on the related record) is set to `nil`
* belongs_to - the source_attribute (on this record) is set to `nil`
* `{:unrelate, :action_name}` - the record is unrelated using the provided update action. The action should be:
* many_to_many - a destroy action on the join resource
* has_many - an update action on the destination resource
@ -1713,9 +1713,9 @@ defmodule Ash.Changeset do
* `:error` - an error is returned indicating that a record would have been updated
* `:unrelate` - the related item is not destroyed, but the data is "unrelated", making this behave like `remove_from_relationship/3`. The action should be:
* many_to_many - the join resource row is destroyed
* has_many - the destination_field (on the related record) is set to `nil`
* has_one - the destination_field (on the related record) is set to `nil`
* belongs_to - the source_field (on this record) is set to `nil`
* has_many - the destination_attribute (on the related record) is set to `nil`
* has_one - the destination_attribute (on the related record) is set to `nil`
* belongs_to - the source_attribute (on this record) is set to `nil`
* `{:unrelate, :action_name}` - the record is unrelated using the provided update action. The action should be:
* many_to_many - a destroy action on the join resource
* has_many - an update action on the destination resource
@ -2043,7 +2043,7 @@ defmodule Ash.Changeset do
Enum.find_value(pkeys, fn pkey ->
this_filter =
pkey
|> Enum.reject(&(&1.name == relationship.destination_field))
|> Enum.reject(&(&1.name == relationship.destination_attribute))
|> Enum.all?(fn key ->
case fetch_identity_field(
item,
@ -2072,14 +2072,14 @@ defmodule Ash.Changeset do
nil
end
if Enum.any?(pkey, &(&1.name == relationship.destination_field)) &&
if Enum.any?(pkey, &(&1.name == relationship.destination_attribute)) &&
relationship.type in [:has_many, :has_one] do
destination_value = Map.get(changeset.data, relationship.source_field)
destination_value = Map.get(changeset.data, relationship.source_attribute)
Ash.Query.expr(
^this_filter and
(is_nil(ref(^relationship.destination_field, [])) or
ref(^relationship.destination_field, []) == ^destination_value)
(is_nil(ref(^relationship.destination_attribute, [])) or
ref(^relationship.destination_attribute, []) == ^destination_value)
)
else
this_filter
@ -2172,9 +2172,9 @@ defmodule Ash.Changeset do
end
defp fetch_identity_field(item, data, attribute, relationship) do
if attribute.name == relationship.destination_field &&
if attribute.name == relationship.destination_attribute &&
relationship.type in [:has_many, :has_one] do
{:ok, Map.get(data, relationship.source_field)}
{:ok, Map.get(data, relationship.source_attribute)}
else
string_attribute = to_string(attribute.name)

View file

@ -1354,8 +1354,8 @@ defmodule Ash.Filter do
relationship.through
|> Ash.Query.new(api)
|> Ash.Query.do_filter([
{relationship.destination_field_on_join_table,
in: Enum.map(results, &Map.get(&1, relationship.destination_field))}
{relationship.destination_attribute_on_join_resource,
in: Enum.map(results, &Map.get(&1, relationship.destination_attribute))}
])
|> filter_related_in(
Ash.Resource.Info.relationship(resource, join_relationship),
@ -1429,9 +1429,9 @@ defmodule Ash.Filter do
%Ref{
relationship_path: path,
resource: relationship.source,
attribute: Ash.Resource.Info.attribute(relationship.source, relationship.source_field)
attribute: Ash.Resource.Info.attribute(relationship.source, relationship.source_attribute)
},
Map.get(single_record, relationship.destination_field)
Map.get(single_record, relationship.destination_attribute)
)
end

View file

@ -63,7 +63,7 @@ defmodule Ash.Generator do
resource
|> Ash.Resource.Info.attributes()
|> Enum.reject(fn attribute ->
Enum.any?(relationships, &(&1.source_field == attribute.name))
Enum.any?(relationships, &(&1.source_attribute == attribute.name))
end)
|> generate_attributes(generators, true, :create)
end

View file

@ -18,9 +18,9 @@ defmodule Ash.Policy.Check.RelatingToActor do
raise "Can only use `belongs_to` relationships in relating_to_actor checks"
end
if Ash.Changeset.changing_attribute?(changeset, relationship.source_field) do
Ash.Changeset.get_attribute(changeset, relationship.source_field) ==
Map.get(actor, relationship.destination_field)
if Ash.Changeset.changing_attribute?(changeset, relationship.source_attribute) do
Ash.Changeset.get_attribute(changeset, relationship.source_attribute) ==
Map.get(actor, relationship.destination_attribute)
else
false
end

View file

@ -29,14 +29,14 @@ defmodule Ash.Query.Aggregate do
def kinds, do: @kinds
def new(resource, name, kind, relationship, query, field, default \\ nil, filterable? \\ true) do
field_type =
attribute_type =
if field do
related = Ash.Resource.Info.related(resource, relationship)
Ash.Resource.Info.attribute(related, field).type
end
with :ok <- validate_path(resource, List.wrap(relationship)),
{:ok, type} <- kind_to_type(kind, field_type),
{:ok, type} <- kind_to_type(kind, attribute_type),
{:ok, query} <- validate_query(query) do
{:ok,
%__MODULE__{
@ -114,11 +114,11 @@ defmodule Ash.Query.Aggregate do
end
@doc false
def kind_to_type(:count, _field_type), do: {:ok, Ash.Type.Integer}
def kind_to_type(:count, _attribute_type), do: {:ok, Ash.Type.Integer}
def kind_to_type(kind, nil), do: {:error, "Must provide field type for #{kind}"}
def kind_to_type(kind, field_type) when kind in [:first, :sum], do: {:ok, field_type}
def kind_to_type(:list, field_type), do: {:ok, {:array, field_type}}
def kind_to_type(kind, _field_type), do: {:error, "Invalid aggregate kind: #{kind}"}
def kind_to_type(kind, attribute_type) when kind in [:first, :sum], do: {:ok, attribute_type}
def kind_to_type(:list, attribute_type), do: {:ok, {:array, attribute_type}}
def kind_to_type(kind, _attribute_type), do: {:error, "Invalid aggregate kind: #{kind}"}
def requests(initial_query, can_be_in_query?, authorizing?, calculations_in_query, request_path) do
initial_query.aggregates

View file

@ -1644,7 +1644,7 @@ defmodule Ash.Query do
relationship ->
cond do
!selecting?(query, relationship.source_field) ->
!selecting?(query, relationship.source_attribute) ->
[
{:error,
"Cannot load a relationship if you are not selecting the source field of that relationship"}

View file

@ -155,8 +155,8 @@ defmodule Ash.Resource.Dsl do
"""
# In a resource called `Word`
has_one :dictionary_entry, DictionaryEntry do
source_field :text
destination_field :word_text
source_attribute :text
destination_attribute :word_text
end
"""
],
@ -180,8 +180,8 @@ defmodule Ash.Resource.Dsl do
"""
# In a resource called `Word`
has_many :definitions, DictionaryDefinition do
source_field :text
destination_field :word_text
source_attribute :text
destination_attribute :word_text
end
"""
],
@ -213,10 +213,10 @@ defmodule Ash.Resource.Dsl do
# In a resource called `Word`
many_to_many :books, Book do
through BookWord
source_field :text
source_field_on_join_table :word_text
destination_field :id
destination_field_on_join_table :book_id
source_attribute :text
source_attribute_on_join_resource :word_text
destination_attribute :id
destination_attribute_on_join_resource :book_id
end
# And in `BookWord` (the resource that defines the join table)
@ -236,7 +236,7 @@ defmodule Ash.Resource.Dsl do
describe: """
Declares a belongs_to relationship. In a relational database, the foreign key would be on the *source* table.
This creates a field on the resource with the corresponding name and type, unless `define_field?: false` is provided.
This creates a field on the resource with the corresponding name and type, unless `define_attribute?: false` is provided.
""",
links: [
guides: [
@ -247,8 +247,8 @@ defmodule Ash.Resource.Dsl do
"""
# In a resource called `Word`
belongs_to :dictionary_entry, DictionaryEntry do
source_field :text,
destination_field :word_text
source_attribute :text,
destination_attribute :word_text
end
"""
],
@ -289,19 +289,19 @@ defmodule Ash.Resource.Dsl do
many_to_many :categories, MyApp.Category do
through MyApp.PostCategory
destination_field_on_join_table :category_id
source_field_on_join_table :post_id
destination_attribute_on_join_resource :category_id
source_attribute_on_join_resource :post_id
end
end
""",
"""
relationships do
has_many :posts, MyApp.Post do
destination_field :author_id
destination_attribute :author_id
end
has_many :composite_key_posts, MyApp.CompositeKeyPost do
destination_field :author_id
destination_attribute :author_id
end
end
"""

View file

@ -56,12 +56,12 @@ defmodule Ash.Resource.Info do
defp reverse_relationship?(rel, destination_rel) do
rel.source == destination_rel.destination &&
rel.destination == destination_rel.source &&
rel.source_field == destination_rel.destination_field &&
rel.destination_field == destination_rel.source_field &&
Map.fetch(rel, :source_field_on_join_table) ==
Map.fetch(destination_rel, :destination_field_on_join_table) &&
Map.fetch(rel, :destination_field_on_join_table) ==
Map.fetch(destination_rel, :source_field_on_join_table) &&
rel.source_attribute == destination_rel.destination_attribute &&
rel.destination_attribute == destination_rel.source_attribute &&
Map.fetch(rel, :source_attribute_on_join_resource) ==
Map.fetch(destination_rel, :destination_attribute_on_join_resource) &&
Map.fetch(rel, :destination_attribute_on_join_resource) ==
Map.fetch(destination_rel, :source_attribute_on_join_resource) &&
is_nil(destination_rel.context) &&
is_nil(rel.context)
end

View file

@ -5,11 +5,11 @@ defmodule Ash.Resource.Relationships.BelongsTo do
:name,
:destination,
:primary_key?,
:define_field?,
:field_type,
:destination_field,
:define_attribute?,
:attribute_type,
:destination_attribute,
:private?,
:source_field,
:source_attribute,
:source,
:read_action,
:api,
@ -22,7 +22,7 @@ defmodule Ash.Resource.Relationships.BelongsTo do
:context,
:description,
:attribute_writable?,
validate_destination_field?: true,
validate_destination_attribute?: true,
cardinality: :one,
type: :belongs_to
]
@ -38,13 +38,13 @@ defmodule Ash.Resource.Relationships.BelongsTo do
destination: Ash.Resource.t(),
required?: boolean,
primary_key?: boolean,
define_field?: boolean,
field_type: term,
define_attribute?: boolean,
attribute_type: term,
writable?: boolean,
attribute_writable?: boolean,
destination_field: atom,
destination_attribute: atom,
private?: boolean,
source_field: atom | nil,
source_attribute: atom | nil,
description: String.t()
}
@ -53,8 +53,8 @@ defmodule Ash.Resource.Relationships.BelongsTo do
alias Spark.OptionsHelpers
@global_opts shared_options()
|> OptionsHelpers.set_default!(:destination_field, :id)
|> OptionsHelpers.append_doc!(:source_field, "Defaults to <name>_id")
|> OptionsHelpers.set_default!(:destination_attribute, :id)
|> OptionsHelpers.append_doc!(:source_attribute, "Defaults to <name>_id")
|> Keyword.delete(:could_be_related_at_creation?)
@opt_schema Spark.OptionsHelpers.merge_schemas(
@ -87,7 +87,7 @@ defmodule Ash.Resource.Relationships.BelongsTo do
Whether the generated attribute will be marked as public & writable.
"""
],
define_field?: [
define_attribute?: [
type: :boolean,
default: true,
links: [
@ -96,7 +96,7 @@ defmodule Ash.Resource.Relationships.BelongsTo do
doc:
"If set to `false` an attribute is not created on the resource for this relationship, and one must be manually added in `attributes`, invalidating many other options."
],
field_type: [
attribute_type: [
type: :any,
links: [
modules: [

View file

@ -3,9 +3,9 @@ defmodule Ash.Resource.Relationships.HasMany do
defstruct [
:name,
:destination,
:destination_field,
:destination_attribute,
:private?,
:source_field,
:source_attribute,
:source,
:context,
:description,
@ -17,9 +17,9 @@ defmodule Ash.Resource.Relationships.HasMany do
:manual,
:api,
:writable?,
no_fields?: false,
no_attributes?: false,
could_be_related_at_creation?: false,
validate_destination_field?: true,
validate_destination_attribute?: true,
cardinality: :many,
type: :has_many
]
@ -30,14 +30,14 @@ defmodule Ash.Resource.Relationships.HasMany do
source: Ash.Resource.t(),
read_action: atom,
filter: Ash.Filter.t() | nil,
no_fields?: boolean,
no_attributes?: boolean,
name: atom,
type: Ash.Type.t(),
writable?: boolean,
destination: Ash.Resource.t(),
destination_field: atom,
destination_attribute: atom,
private?: boolean,
source_field: atom,
source_attribute: atom,
description: String.t(),
manual: atom | {atom, Keyword.t()} | nil
}
@ -46,12 +46,12 @@ defmodule Ash.Resource.Relationships.HasMany do
alias Spark.OptionsHelpers
@global_opts shared_options()
|> OptionsHelpers.set_default!(:source_field, :id)
|> OptionsHelpers.set_default!(:source_attribute, :id)
@opt_schema Spark.OptionsHelpers.merge_schemas(
[
manual(),
no_fields()
no_attributes()
],
@global_opts,
"Relationship Options"

View file

@ -5,9 +5,9 @@ defmodule Ash.Resource.Relationships.HasOne do
:name,
:source,
:destination,
:destination_field,
:destination_attribute,
:private?,
:source_field,
:source_attribute,
:allow_orphans?,
:context,
:description,
@ -19,9 +19,9 @@ defmodule Ash.Resource.Relationships.HasOne do
:violation_message,
:manual,
:writable?,
no_fields?: false,
no_attributes?: false,
could_be_related_at_creation?: false,
validate_destination_field?: true,
validate_destination_attribute?: true,
cardinality: :one,
type: :has_one,
required?: false
@ -33,14 +33,14 @@ defmodule Ash.Resource.Relationships.HasOne do
source: Ash.Resource.t(),
name: atom,
read_action: atom,
no_fields?: boolean,
no_attributes?: boolean,
writable?: boolean,
type: Ash.Type.t(),
filter: Ash.Filter.t() | nil,
destination: Ash.Resource.t(),
destination_field: atom,
destination_attribute: atom,
private?: boolean,
source_field: atom,
source_attribute: atom,
allow_orphans?: boolean,
description: String.t(),
manual: atom | {atom, Keyword.t()} | nil
@ -50,10 +50,10 @@ defmodule Ash.Resource.Relationships.HasOne do
alias Spark.OptionsHelpers
@global_opts shared_options()
|> OptionsHelpers.set_default!(:source_field, :id)
|> OptionsHelpers.set_default!(:source_attribute, :id)
@opt_schema Spark.OptionsHelpers.merge_schemas(
[manual(), no_fields()] ++
[manual(), no_attributes()] ++
[
required?: [
type: :boolean,

View file

@ -5,10 +5,10 @@ defmodule Ash.Resource.Relationships.ManyToMany do
:source,
:through,
:destination,
:source_field,
:destination_field,
:source_field_on_join_table,
:destination_field_on_join_table,
:source_attribute,
:destination_attribute,
:source_attribute_on_join_resource,
:destination_attribute_on_join_resource,
:join_relationship,
:not_found_message,
:violation_message,
@ -21,7 +21,7 @@ defmodule Ash.Resource.Relationships.ManyToMany do
:filter,
:has_many,
could_be_related_at_creation?: false,
validate_destination_field?: true,
validate_destination_attribute?: true,
cardinality: :many,
type: :many_to_many
]
@ -38,10 +38,10 @@ defmodule Ash.Resource.Relationships.ManyToMany do
through: Ash.Resource.t(),
destination: Ash.Resource.t(),
join_relationship: atom,
source_field: atom,
destination_field: atom,
source_field_on_join_table: atom,
destination_field_on_join_table: atom,
source_attribute: atom,
destination_attribute: atom,
source_attribute_on_join_resource: atom,
destination_attribute_on_join_resource: atom,
description: String.t()
}
@ -49,12 +49,12 @@ defmodule Ash.Resource.Relationships.ManyToMany do
alias Spark.OptionsHelpers
@global_opts shared_options()
|> OptionsHelpers.set_default!(:destination_field, :id)
|> OptionsHelpers.set_default!(:source_field, :id)
|> OptionsHelpers.set_default!(:destination_attribute, :id)
|> OptionsHelpers.set_default!(:source_attribute, :id)
@opt_schema Spark.OptionsHelpers.merge_schemas(
[
source_field_on_join_table: [
source_attribute_on_join_resource: [
type: :atom,
required: true,
links: [
@ -63,9 +63,9 @@ defmodule Ash.Resource.Relationships.ManyToMany do
]
],
doc:
"The attribute on the join resource that should line up with `source_field` on this resource."
"The attribute on the join resource that should line up with `source_attribute` on this resource."
],
destination_field_on_join_table: [
destination_attribute_on_join_resource: [
type: :atom,
required: true,
links: [
@ -74,7 +74,7 @@ defmodule Ash.Resource.Relationships.ManyToMany do
]
],
doc:
"The attribute on the join resource that should line up with `destination_field` on the related resource."
"The attribute on the join resource that should line up with `destination_attribute` on the related resource."
],
through: [
type: Ash.OptionsHelpers.ash_resource(),

View file

@ -19,7 +19,7 @@ defmodule Ash.Resource.Relationships.SharedOptions do
modules: ["ash:guide:Documentation"]
]
],
destination_field: [
destination_attribute: [
type: :atom,
links: [
dsls: [
@ -27,16 +27,16 @@ defmodule Ash.Resource.Relationships.SharedOptions do
]
],
doc:
"The attribute on the related resource that should match the `source_field` configured on this resource."
"The attribute on the related resource that should match the `source_attribute` configured on this resource."
],
validate_destination_field?: [
validate_destination_attribute?: [
type: :boolean,
default: true,
doc:
"Whether or not to validate that the destination field exists on the destination resource",
links: []
],
source_field: [
source_attribute: [
type: :atom,
links: [
dsls: [
@ -44,7 +44,7 @@ defmodule Ash.Resource.Relationships.SharedOptions do
]
],
doc:
"The field on this resource that should match the `destination_field` on the related resource."
"The field on this resource that should match the `destination_attribute` on the related resource."
],
relationship_context: [
type: :any,
@ -134,18 +134,18 @@ defmodule Ash.Resource.Relationships.SharedOptions do
@shared_options
end
def no_fields do
{:no_fields?,
def no_attributes do
{:no_attributes?,
[
type: :boolean,
links: [],
doc: """
If true, all existing entities are considered related, i.e this relationship is not based on any fields, and `source_field` and
`destination_field` are ignored.
If true, all existing entities are considered related, i.e this relationship is not based on any fields, and `source_attribute` and
`destination_attribute` are ignored.
This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource like `Organization`,
you can use `no_fields?` to do things like `has_many :employees, Employee, no_fields?: true`, which lets you avoid having an
unnecessary `organization_id` field on `Employee`. The same works in reverse: `has_one :organization, Organization, no_fields?: true`
you can use `no_attributes?` to do things like `has_many :employees, Employee, no_attributes?: true`, which lets you avoid having an
unnecessary `organization_id` field on `Employee`. The same works in reverse: `has_one :organization, Organization, no_attributes?: true`
allows relating the employee to their organization.
Some important caveats here:

View file

@ -1,6 +1,6 @@
defmodule Ash.Resource.Transformers.BelongsToAttribute do
@moduledoc """
Creates the attribute for belongs_to relationships that have `define_field?: true`
Creates the attribute for belongs_to relationships that have `define_attribute?: true`
"""
use Spark.Dsl.Transformer
@ -12,17 +12,17 @@ defmodule Ash.Resource.Transformers.BelongsToAttribute do
def transform(resource, dsl_state) do
dsl_state
|> Transformer.get_entities([:relationships])
|> Enum.filter(&(&1.type == :belongs_to && &1.define_field?))
|> Enum.filter(&(&1.type == :belongs_to && &1.define_attribute?))
|> Enum.reject(fn relationship ->
dsl_state
|> Transformer.get_entities([:attributes])
|> Enum.find(&(Map.get(&1, :name) == relationship.source_field))
|> Enum.find(&(Map.get(&1, :name) == relationship.source_attribute))
end)
|> Enum.reduce_while({:ok, dsl_state}, fn relationship, {:ok, dsl_state} ->
entity =
Transformer.build_entity(@extension, [:attributes], :attribute,
name: relationship.source_field,
type: relationship.field_type || :uuid,
name: relationship.source_attribute,
type: relationship.attribute_type || :uuid,
allow_nil?:
if relationship.primary_key? do
false

View file

@ -1,6 +1,6 @@
defmodule Ash.Resource.Transformers.BelongsToSourceField do
@moduledoc """
Sets the default `source_field` for belongs_to attributes
Sets the default `source_attribute` for belongs_to attributes
"""
use Spark.Dsl.Transformer
@ -11,13 +11,13 @@ defmodule Ash.Resource.Transformers.BelongsToSourceField do
dsl_state
|> Transformer.get_entities([:relationships])
|> Enum.filter(&(&1.type == :belongs_to))
|> Enum.reject(& &1.source_field)
|> Enum.reject(& &1.source_attribute)
|> Enum.reduce({:ok, dsl_state}, fn relationship, {:ok, dsl_state} ->
new_dsl_state =
Transformer.replace_entity(
dsl_state,
[:relationships],
%{relationship | source_field: :"#{relationship.name}_id"},
%{relationship | source_attribute: :"#{relationship.name}_id"},
&(&1.name == relationship.name)
)

View file

@ -29,9 +29,9 @@ defmodule Ash.Resource.Transformers.CreateJoinRelationship do
[
name: relationship.join_relationship,
destination: relationship.through,
destination_field: relationship.source_field_on_join_table,
destination_attribute: relationship.source_attribute_on_join_resource,
api: relationship.api,
source_field: relationship.source_field,
source_attribute: relationship.source_attribute,
private?: true
]
|> add_messages(relationship)

View file

@ -1,5 +1,5 @@
defmodule Ash.Resource.Transformers.HasDestinationField do
@moduledoc "Guesses the `destination_field` for has many and has one relationships unless provided"
@moduledoc "Guesses the `destination_attribute` for has many and has one relationships unless provided"
use Spark.Dsl.Transformer
alias Spark.Dsl.Transformer
@ -9,9 +9,9 @@ defmodule Ash.Resource.Transformers.HasDestinationField do
dsl_state
|> Transformer.get_entities([:relationships])
|> Enum.reduce(dsl_state, fn
%{type: type, destination_field: nil} = relationship, dsl_state
%{type: type, destination_attribute: nil} = relationship, dsl_state
when type in [:has_many, :has_one] ->
new_relationship = %{relationship | destination_field: resource_id_field(resource)}
new_relationship = %{relationship | destination_attribute: resource_id_field(resource)}
Transformer.replace_entity(
dsl_state,

View file

@ -17,21 +17,21 @@ defmodule Ash.Resource.Transformers.ValidateRelationshipAttributes do
resource
|> Ash.Resource.Info.relationships()
|> Enum.reject(fn relationship ->
Map.get(relationship, :manual) || Map.get(relationship, :no_fields?)
Map.get(relationship, :manual) || Map.get(relationship, :no_attributes?)
end)
|> Enum.filter(& &1.validate_destination_field?)
|> Enum.filter(& &1.validate_destination_attribute?)
|> Enum.each(&validate_relationship(&1, attribute_names, resource))
{:ok, dsl}
end
defp validate_relationship(relationship, attribute_names, resource) do
unless relationship.source_field in attribute_names do
unless relationship.source_attribute in attribute_names do
raise Spark.Error.DslError,
module: resource,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects source field `#{relationship.source_field}` to be defined"
"Relationship `#{relationship.name}` expects source field `#{relationship.source_attribute}` to be defined"
end
if Code.ensure_loaded?(relationship.destination) do
@ -42,20 +42,20 @@ defmodule Ash.Resource.Transformers.ValidateRelationshipAttributes do
|> Ash.Resource.Info.attributes()
|> Enum.map(& &1.name)
unless relationship.source_field_on_join_table in through_attributes do
unless relationship.source_attribute_on_join_resource in through_attributes do
raise Spark.Error.DslError,
module: resource,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects source field on join table `#{relationship.source_field_on_join_table}` to be defined on #{inspect(relationship.through)}"
"Relationship `#{relationship.name}` expects source field on join table `#{relationship.source_attribute_on_join_resource}` to be defined on #{inspect(relationship.through)}"
end
unless relationship.destination_field_on_join_table in through_attributes do
unless relationship.destination_attribute_on_join_resource in through_attributes do
raise Spark.Error.DslError,
module: resource,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects destination field on join table `#{relationship.destination_field_on_join_table}` to be defined on #{inspect(relationship.through)}"
"Relationship `#{relationship.name}` expects destination field on join table `#{relationship.destination_attribute_on_join_resource}` to be defined on #{inspect(relationship.through)}"
end
end
end
@ -65,12 +65,12 @@ defmodule Ash.Resource.Transformers.ValidateRelationshipAttributes do
|> Ash.Resource.Info.attributes()
|> Enum.map(& &1.name)
unless relationship.destination_field in destination_attributes do
unless relationship.destination_attribute in destination_attributes do
raise Spark.Error.DslError,
module: resource,
path: [:relationships, relationship.name],
message:
"Relationship `#{relationship.name}` expects destination field `#{relationship.destination_field}` to be defined on #{inspect(relationship.destination)}"
"Relationship `#{relationship.name}` expects destination field `#{relationship.destination_attribute}` to be defined on #{inspect(relationship.destination)}"
end
end
end

View file

@ -43,7 +43,7 @@ defmodule Ash.Resource.Validation do
:validation,
:module,
:opts,
:expensive?,
:only_when_valid?,
:description,
:message,
:before_action?,
@ -55,7 +55,7 @@ defmodule Ash.Resource.Validation do
validation: {atom(), list(atom())},
module: atom(),
opts: list(atom()),
expensive?: boolean(),
only_when_valid?: boolean(),
description: String.t() | nil,
where: list({atom(), list(atom())}),
on: list(atom())
@ -97,12 +97,12 @@ defmodule Ash.Resource.Validation do
Many validations don't make sense in the context of deletion, so by default it is left out of the list.
"""
],
expensive?: [
only_when_valid?: [
type: :boolean,
default: false,
links: [],
doc:
"If a validation is expensive, it won't be run on invalid changes. All inexpensive validations are always run, to provide informative errors."
"If the validation should only run on valid changes. Useful for expensive validations or validations that depend on valid data."
],
message: [
type: :string,

View file

@ -38,8 +38,8 @@ defmodule Ash.Resource.Validation.Changing do
)}
end
%{type: :belongs_to, source_field: source_field} = relationship ->
if Ash.Changeset.changing_attribute?(changeset, source_field) ||
%{type: :belongs_to, source_attribute: source_attribute} = relationship ->
if Ash.Changeset.changing_attribute?(changeset, source_attribute) ||
Ash.Changeset.changing_relationship?(changeset, relationship.name) do
:ok
else

View file

@ -123,8 +123,8 @@ defmodule Ash.Seed do
%{
type: :belongs_to,
source_field: source_field,
destination_field: destination_field,
source_attribute: source_attribute,
destination_attribute: destination_attribute,
destination: destination,
name: name
} ->
@ -133,8 +133,8 @@ defmodule Ash.Seed do
changeset
|> Ash.Changeset.force_change_attribute(
source_field,
Map.get(related, destination_field)
source_attribute,
Map.get(related, destination_attribute)
)
|> callback.()
|> case do
@ -148,8 +148,8 @@ defmodule Ash.Seed do
%{
type: :has_many,
source_field: source_field,
destination_field: destination_field,
source_attribute: source_attribute,
destination_attribute: destination_attribute,
destination: destination,
name: name
} ->
@ -161,8 +161,8 @@ defmodule Ash.Seed do
&update_or_seed!(
&1,
destination,
Map.get(result, source_field),
destination_field
Map.get(result, source_attribute),
destination_attribute
)
)
@ -171,8 +171,8 @@ defmodule Ash.Seed do
%{
type: :has_one,
source_field: source_field,
destination_field: destination_field,
source_attribute: source_attribute,
destination_attribute: destination_attribute,
destination: destination,
name: name
} ->
@ -182,8 +182,8 @@ defmodule Ash.Seed do
update_or_seed!(
value,
destination,
Map.get(result, source_field),
destination_field
Map.get(result, source_attribute),
destination_attribute
)
{:ok, Map.put(result, name, related)}
@ -194,11 +194,11 @@ defmodule Ash.Seed do
%{
type: :many_to_many,
source_field: source_field,
source_field_on_join_table: source_field_on_join_table,
destination_field_on_join_table: destination_field_on_join_table,
source_attribute: source_attribute,
source_attribute_on_join_resource: source_attribute_on_join_resource,
destination_attribute_on_join_resource: destination_attribute_on_join_resource,
join_relationship: join_relationship,
destination_field: destination_field,
destination_attribute: destination_attribute,
destination: destination,
through: through,
name: name
@ -209,8 +209,9 @@ defmodule Ash.Seed do
through =
Enum.map(related, fn related ->
seed!(through, %{
source_field_on_join_table => Map.get(result, source_field),
destination_field_on_join_table => Map.get(related, destination_field)
source_attribute_on_join_resource => Map.get(result, source_attribute),
destination_attribute_on_join_resource =>
Map.get(related, destination_attribute)
})
end)

View file

@ -169,9 +169,9 @@ defmodule Ash.SatSolver do
when path != [] do
with relationship when not is_nil(relationship) <-
Ash.Resource.Info.relationship(resource, path),
true <- attribute.name == relationship.destination_field,
true <- attribute.name == relationship.destination_attribute,
new_attribute when not is_nil(new_attribute) <-
Ash.Resource.Info.attribute(relationship.source, relationship.source_field) do
Ash.Resource.Info.attribute(relationship.source, relationship.source_attribute) do
%{
ref
| relationship_path: :lists.droplast(path),
@ -317,11 +317,11 @@ defmodule Ash.SatSolver do
true ->
comparison_keys = [
:source_field,
:destination_field,
:source_field_on_join_table,
:destination_field_on_join_table,
:destination_field,
:source_attribute,
:destination_attribute,
:source_attribute_on_join_resource,
:destination_attribute_on_join_resource,
:destination_attribute,
:destination
]

View file

@ -329,7 +329,7 @@ a `Tweet` belongs to a specific `User`.
```elixir
# in lib/my_app/resources/user.ex
relationships do
has_many :tweets, MyApp.Tweet, destination_field: :user_id
has_many :tweets, MyApp.Tweet, destination_attribute: :user_id
end
# in lib/my_app/resources/tweet.ex

View file

@ -7,6 +7,18 @@
The DSL tooling has been moved out of the Ash name space and into a more generalized tool called `Spark`. If you have written your own extensions, you will need
to refer to those modules. They are all the same, they simply have different names. You will get compiler errors/warnings on the modules you need to change, for example: `Ash.Dsl` -> `Spark.Dsl` and `Ash.Dsl.Transformer` -> `Spark.Dsl.Transformer`. One exception, `Ash.Error.Dsl.DslError`, has been changed to `Spark.Error.DslError`.
## DSL name changes
These should all be straight forward enough to do a simple find and replace in your resources.
- `source_field` -> `source_attribute`
- `destination_field` -> `destination_attribute`
- `define_field?` -> `define_attribute?`
- `field_type` -> `attribute_type`
- `source_field_on_join_table` -> `source_attribute_on_join_resource`
- `destination_field_on_join_table` -> `destination_attribute_on_join_resource`
- `no_fields?` -> `no_attributes?`
## Upgrading to 1.53
### Default actions

View file

@ -24,18 +24,18 @@ defmodule Ash.Test.Actions.AsyncLoadTest do
end
relationships do
has_many :posts, Ash.Test.Actions.AsyncLoadTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.Actions.AsyncLoadTest.Post, destination_attribute: :author_id
has_many :authorized_actor_posts, Ash.Test.Actions.AsyncLoadTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
read_action: :authorized_actor
has_many :authorized_context_posts, Ash.Test.Actions.AsyncLoadTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
read_action: :authorized_context
has_one :latest_post, Ash.Test.Actions.AsyncLoadTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
sort: [inserted_at: :desc]
end
end
@ -95,8 +95,8 @@ defmodule Ash.Test.Actions.AsyncLoadTest do
many_to_many :categories, Ash.Test.Actions.AsyncLoadTest.Category,
through: Ash.Test.Actions.AsyncLoadTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
policies do
@ -147,8 +147,8 @@ defmodule Ash.Test.Actions.AsyncLoadTest do
relationships do
many_to_many :posts, Post,
through: PostCategory,
destination_field_on_join_table: :post_id,
source_field_on_join_table: :category_id
destination_attribute_on_join_resource: :post_id,
source_attribute_on_join_resource: :category_id
end
end

View file

@ -147,9 +147,9 @@ defmodule Ash.Test.Actions.CreateTest do
end
relationships do
has_one(:profile, Profile, destination_field: :author_id)
has_one(:profile, Profile, destination_attribute: :author_id)
has_many(:posts, Ash.Test.Actions.CreateTest.Post, destination_field: :author_id)
has_many(:posts, Ash.Test.Actions.CreateTest.Post, destination_attribute: :author_id)
end
end
@ -255,8 +255,8 @@ defmodule Ash.Test.Actions.CreateTest do
many_to_many(:related_posts, __MODULE__,
through: PostLink,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
)
end
end

View file

@ -64,9 +64,9 @@ defmodule Ash.Test.Actions.DestroyTest do
end
relationships do
has_one :profile, Profile, destination_field: :author_id
has_one :profile, Profile, destination_attribute: :author_id
has_many :posts, Ash.Test.Actions.DestroyTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.Actions.DestroyTest.Post, destination_attribute: :author_id
end
end

View file

@ -27,10 +27,10 @@ defmodule Ash.Test.Actions.LoadTest do
end
relationships do
has_many :posts, Ash.Test.Actions.LoadTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.Actions.LoadTest.Post, destination_attribute: :author_id
has_one :latest_post, Ash.Test.Actions.LoadTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
sort: [inserted_at: :desc]
end
end
@ -92,8 +92,8 @@ defmodule Ash.Test.Actions.LoadTest do
many_to_many :categories, Ash.Test.Actions.LoadTest.Category,
through: Ash.Test.Actions.LoadTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end
@ -138,8 +138,8 @@ defmodule Ash.Test.Actions.LoadTest do
relationships do
many_to_many :posts, Post,
through: PostCategory,
destination_field_on_join_table: :post_id,
source_field_on_join_table: :category_id
destination_attribute_on_join_resource: :post_id,
source_attribute_on_join_resource: :category_id
end
end

View file

@ -27,8 +27,10 @@ defmodule Ash.Actions.MultitenancyTest do
end
relationships do
has_many :posts, Ash.Actions.MultitenancyTest.Post, destination_field: :author_id
has_many :comments, Ash.Actions.MultitenancyTest.Comment, destination_field: :commenter_id
has_many :posts, Ash.Actions.MultitenancyTest.Post, destination_attribute: :author_id
has_many :comments, Ash.Actions.MultitenancyTest.Comment,
destination_attribute: :commenter_id
end
end
@ -51,7 +53,7 @@ defmodule Ash.Actions.MultitenancyTest do
end
relationships do
has_many :comments, Ash.Actions.MultitenancyTest.Comment, destination_field: :post_id
has_many :comments, Ash.Actions.MultitenancyTest.Comment, destination_attribute: :post_id
belongs_to :author, User
end
end

View file

@ -27,7 +27,7 @@ defmodule Ash.Actions.PaginationTest do
end
relationships do
belongs_to :user, Ash.Actions.PaginationTest.User, define_field?: false
belongs_to :user, Ash.Actions.PaginationTest.User, define_attribute?: false
end
end

View file

@ -36,7 +36,7 @@ defmodule Ash.Test.Actions.ReadTest do
end
relationships do
has_many :posts, Ash.Test.Actions.ReadTest.Post, destination_field: :author1_id
has_many :posts, Ash.Test.Actions.ReadTest.Post, destination_attribute: :author1_id
end
end

View file

@ -119,9 +119,9 @@ defmodule Ash.Test.Actions.UpdateTest do
end
relationships do
has_one :profile, Profile, destination_field: :author_id
has_one :profile, Profile, destination_attribute: :author_id
has_many :posts, Ash.Test.Actions.UpdateTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.Actions.UpdateTest.Post, destination_attribute: :author_id
end
end
@ -175,8 +175,8 @@ defmodule Ash.Test.Actions.UpdateTest do
many_to_many :related_posts, __MODULE__,
through: PostLink,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end

View file

@ -47,8 +47,8 @@ defmodule Ash.Test.Changeset.ChangesetTest do
relationships do
many_to_many :posts, Ash.Test.Changeset.ChangesetTest.Post,
through: Ash.Test.Changeset.ChangesetTest.PostCategory,
destination_field_on_join_table: :post_id,
source_field_on_join_table: :category_id
destination_attribute_on_join_resource: :post_id,
source_attribute_on_join_resource: :category_id
end
end
@ -74,13 +74,13 @@ defmodule Ash.Test.Changeset.ChangesetTest do
end
relationships do
has_many :posts, Ash.Test.Changeset.ChangesetTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.Changeset.ChangesetTest.Post, destination_attribute: :author_id
has_many :unique_posts, Ash.Test.Changeset.ChangesetTest.UniqueNamePerAuthor,
destination_field: :author_id
destination_attribute: :author_id
has_many :composite_key_posts, Ash.Test.Changeset.ChangesetTest.CompositeKeyPost,
destination_field: :author_id
destination_attribute: :author_id
end
end
@ -128,8 +128,8 @@ defmodule Ash.Test.Changeset.ChangesetTest do
many_to_many :categories, Ash.Test.Changeset.ChangesetTest.Category,
through: Ash.Test.Changeset.ChangesetTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end
@ -157,8 +157,8 @@ defmodule Ash.Test.Changeset.ChangesetTest do
many_to_many :categories, Ash.Test.Changeset.ChangesetTest.Category,
through: Ash.Test.Changeset.ChangesetTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end
@ -190,8 +190,8 @@ defmodule Ash.Test.Changeset.ChangesetTest do
many_to_many :categories, Ash.Test.Changeset.ChangesetTest.Category,
through: Ash.Test.Changeset.ChangesetTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end

View file

@ -50,13 +50,15 @@ defmodule Ash.Test.Filter.FilterInteractionTest do
end
relationships do
has_many(:posts, Ash.Test.Filter.FilterInteractionTest.Post, destination_field: :author_id)
has_many(:second_posts, Ash.Test.Filter.FilterInteractionTest.Post,
destination_field: :author_id
has_many(:posts, Ash.Test.Filter.FilterInteractionTest.Post,
destination_attribute: :author_id
)
has_one(:profile, Profile, destination_field: :user_id)
has_many(:second_posts, Ash.Test.Filter.FilterInteractionTest.Post,
destination_attribute: :author_id
)
has_one(:profile, Profile, destination_attribute: :user_id)
end
end
@ -98,14 +100,14 @@ defmodule Ash.Test.Filter.FilterInteractionTest do
relationships do
belongs_to(:author, User,
destination_field: :id,
source_field: :author_id
destination_attribute: :id,
source_attribute: :author_id
)
many_to_many(:related_posts, __MODULE__,
through: PostLink,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
)
end
end

View file

@ -64,11 +64,11 @@ defmodule Ash.Test.Filter.FilterTest do
end
relationships do
has_many :posts, Ash.Test.Filter.FilterTest.Post, destination_field: :author1_id
has_many :posts, Ash.Test.Filter.FilterTest.Post, destination_attribute: :author1_id
has_many :second_posts, Ash.Test.Filter.FilterTest.Post, destination_field: :author1_id
has_many :second_posts, Ash.Test.Filter.FilterTest.Post, destination_attribute: :author1_id
has_one :profile, Profile, destination_field: :user_id
has_one :profile, Profile, destination_attribute: :user_id
end
end
@ -118,23 +118,23 @@ defmodule Ash.Test.Filter.FilterTest do
relationships do
belongs_to :author1, User,
destination_field: :id,
source_field: :author1_id
destination_attribute: :id,
source_attribute: :author1_id
belongs_to :special_author1, User,
destination_field: :id,
source_field: :author1_id,
define_field?: false,
destination_attribute: :id,
source_attribute: :author1_id,
define_attribute?: false,
filter: expr(special == true)
belongs_to :author2, User,
destination_field: :id,
source_field: :author2_id
destination_attribute: :id,
source_attribute: :author2_id
many_to_many :related_posts, __MODULE__,
through: PostLink,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end

View file

@ -25,10 +25,10 @@ defmodule Ash.Test.GeneratorTest do
end
relationships do
has_many :posts, Ash.Test.GeneratorTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.GeneratorTest.Post, destination_attribute: :author_id
has_one :latest_post, Ash.Test.GeneratorTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
sort: [inserted_at: :desc]
end
end
@ -60,8 +60,8 @@ defmodule Ash.Test.GeneratorTest do
many_to_many :categories, Ash.Test.GeneratorTest.Category,
through: Ash.Test.GeneratorTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end
@ -110,8 +110,8 @@ defmodule Ash.Test.GeneratorTest do
relationships do
many_to_many :posts, Post,
through: PostCategory,
destination_field_on_join_table: :post_id,
source_field_on_join_table: :category_id
destination_attribute_on_join_resource: :post_id,
source_attribute_on_join_resource: :category_id
end
end

View file

@ -87,10 +87,10 @@ defmodule Ash.Test.NotifierTest do
relationships do
many_to_many :related_posts, __MODULE__,
through: PostLink,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
has_many :comments, Comment, destination_field: :post_id
has_many :comments, Comment, destination_attribute: :post_id
end
end

View file

@ -39,7 +39,7 @@ defmodule Ash.Test.Resource.AggregatesTest do
end
relationships do
has_many :comments, Comment, destination_field: :post_id
has_many :comments, Comment, destination_attribute: :post_id
end
end
@ -85,7 +85,7 @@ defmodule Ash.Test.Resource.AggregatesTest do
end
relationships do
has_many :comments, Comment, destination_field: :post_id
has_many :comments, Comment, destination_attribute: :post_id
end
end

View file

@ -25,12 +25,12 @@ defmodule Ash.Test.Resource.InfoTest do
relationships do
many_to_many :tags, Tag do
through TagOnPost
source_field_on_join_table :vendor_id
destination_field_on_join_table :shipping_method_id
source_attribute_on_join_resource(:vendor_id)
destination_attribute_on_join_resource(:shipping_method_id)
end
has_many :comments, Comment, destination_field: :post_id
has_one :private, PostPrivate, destination_field: :post_id
has_many :comments, Comment, destination_attribute: :post_id
has_one :private, PostPrivate, destination_attribute: :post_id
end
end

View file

@ -78,32 +78,32 @@ defmodule Ash.Test.Resource.Relationships.BelongsToTest do
defposts do
relationships do
belongs_to(:foo, Foo)
belongs_to(:bar, Bar, source_field: :bazz, private?: true)
belongs_to(:bar, Bar, source_attribute: :bazz, private?: true)
end
end
assert [
%BelongsTo{
cardinality: :one,
define_field?: true,
define_attribute?: true,
destination: Foo,
destination_field: :id,
field_type: :uuid,
destination_attribute: :id,
attribute_type: :uuid,
name: :foo,
primary_key?: false,
source_field: :foo_id,
source_attribute: :foo_id,
type: :belongs_to,
private?: false
},
%BelongsTo{
cardinality: :one,
define_field?: true,
define_attribute?: true,
destination: Bar,
destination_field: :id,
field_type: :uuid,
destination_attribute: :id,
attribute_type: :uuid,
name: :bar,
primary_key?: false,
source_field: :bazz,
source_attribute: :bazz,
type: :belongs_to,
private?: true
}
@ -120,28 +120,28 @@ defmodule Ash.Test.Resource.Relationships.BelongsToTest do
end
describe "validations" do
test "fails if destination_field is not an atom" do
test "fails if destination_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :destination_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :destination_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
belongs_to(:foobar, FooBar, destination_field: "foo")
belongs_to(:foobar, FooBar, destination_attribute: "foo")
end
end
end
)
end
test "fails if source_field is not an atom" do
test "fails if source_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :source_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :source_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
belongs_to(:foobar, FooBar, source_field: "foo")
belongs_to(:foobar, FooBar, source_attribute: "foo")
end
end
end
@ -205,14 +205,14 @@ defmodule Ash.Test.Resource.Relationships.BelongsToTest do
end
end
test "fails if `define_field?` is not a boolean" do
test "fails if `define_attribute?` is not a boolean" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :define_field? to be a boolean, got: \"blah\"",
"[Ash.Test.Resource.Relationships.BelongsToTest.Post]\n relationships -> belongs_to -> foobar:\n expected :define_attribute? to be a boolean, got: \"blah\"",
fn ->
defposts do
relationships do
belongs_to(:foobar, Foobar, define_field?: "blah")
belongs_to(:foobar, Foobar, define_attribute?: "blah")
end
end
end
@ -226,7 +226,7 @@ defmodule Ash.Test.Resource.Relationships.BelongsToTest do
fn ->
defposts do
relationships do
belongs_to(:post, __MODULE__, define_field?: false)
belongs_to(:post, __MODULE__, define_attribute?: false)
end
end

View file

@ -24,7 +24,7 @@ defmodule Ash.Test.Resource.Relationships.HasManyTest do
defposts do
relationships do
has_many :foo, Foo
has_many :bar, Bar, destination_field: :bazz, private?: true
has_many :bar, Bar, destination_attribute: :bazz, private?: true
end
end
@ -32,18 +32,18 @@ defmodule Ash.Test.Resource.Relationships.HasManyTest do
%HasMany{
cardinality: :many,
destination: Foo,
destination_field: :post_id,
destination_attribute: :post_id,
name: :foo,
source_field: :id,
source_attribute: :id,
type: :has_many,
private?: false
},
%HasMany{
cardinality: :many,
destination: Bar,
destination_field: :bazz,
destination_attribute: :bazz,
name: :bar,
source_field: :id,
source_attribute: :id,
type: :has_many,
private?: true
}
@ -60,28 +60,28 @@ defmodule Ash.Test.Resource.Relationships.HasManyTest do
end
describe "validations" do
test "fails if destination_field is not an atom" do
test "fails if destination_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.HasManyTest.Post]\n relationships -> has_many -> foobar:\n expected :destination_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.HasManyTest.Post]\n relationships -> has_many -> foobar:\n expected :destination_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
has_many :foobar, FooBar, destination_field: "foo"
has_many :foobar, FooBar, destination_attribute: "foo"
end
end
end
)
end
test "fails if source_field is not an atom" do
test "fails if source_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.HasManyTest.Post]\n relationships -> has_many -> foobar:\n expected :source_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.HasManyTest.Post]\n relationships -> has_many -> foobar:\n expected :source_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
has_many :foobar, FooBar, source_field: "foo", destination_field: :post_id
has_many :foobar, FooBar, source_attribute: "foo", destination_attribute: :post_id
end
end
end
@ -123,7 +123,7 @@ defmodule Ash.Test.Resource.Relationships.HasManyTest do
fn ->
defposts do
relationships do
has_many :foobar, FooBar, private?: "foo", destination_field: :post_id
has_many :foobar, FooBar, private?: "foo", destination_attribute: :post_id
end
end
end

View file

@ -23,8 +23,8 @@ defmodule Ash.Test.Resource.Relationships.HasOneTest do
test "it creates a relationship" do
defposts do
relationships do
has_one :foo, Foo, destination_field: :post_id
has_one :bar, Bar, destination_field: :post_id, private?: true
has_one :foo, Foo, destination_attribute: :post_id
has_one :bar, Bar, destination_attribute: :post_id, private?: true
end
end
@ -32,18 +32,18 @@ defmodule Ash.Test.Resource.Relationships.HasOneTest do
%HasOne{
cardinality: :one,
destination: Foo,
destination_field: :post_id,
destination_attribute: :post_id,
name: :foo,
source_field: :id,
source_attribute: :id,
type: :has_one,
private?: false
},
%HasOne{
cardinality: :one,
destination: Bar,
destination_field: :post_id,
destination_attribute: :post_id,
name: :bar,
source_field: :id,
source_attribute: :id,
type: :has_one,
private?: true
}
@ -60,28 +60,28 @@ defmodule Ash.Test.Resource.Relationships.HasOneTest do
end
describe "validations" do
test "fails if destination_field is not an atom" do
test "fails if destination_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.HasOneTest.Post]\n relationships -> has_one -> foobar:\n expected :destination_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.HasOneTest.Post]\n relationships -> has_one -> foobar:\n expected :destination_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
has_one :foobar, FooBar, destination_field: "foo"
has_one :foobar, FooBar, destination_attribute: "foo"
end
end
end
)
end
test "fails if source_field is not an atom" do
test "fails if source_attribute is not an atom" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.HasOneTest.Post]\n relationships -> has_one -> foobar:\n expected :source_field to be an atom, got: \"foo\"",
"[Ash.Test.Resource.Relationships.HasOneTest.Post]\n relationships -> has_one -> foobar:\n expected :source_attribute to be an atom, got: \"foo\"",
fn ->
defposts do
relationships do
has_one :foobar, FooBar, source_field: "foo", destination_field: :post_id
has_one :foobar, FooBar, source_attribute: "foo", destination_attribute: :post_id
end
end
end
@ -123,7 +123,7 @@ defmodule Ash.Test.Resource.Relationships.HasOneTest do
fn ->
defposts do
relationships do
has_one :foobar, FooBar, private?: "foo", destination_field: :post_id
has_one :foobar, FooBar, private?: "foo", destination_attribute: :post_id
end
end
end

View file

@ -27,13 +27,13 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
relationships do
many_to_many :related_posts, Post,
through: SomeResource,
source_field_on_join_table: :post_id,
destination_field_on_join_table: :related_post_id
source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :related_post_id
many_to_many :unrelated_posts, Post,
through: Tabloid,
source_field_on_join_table: :post_id,
destination_field_on_join_table: :unrelated_post_id,
source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :unrelated_post_id,
private?: true
end
end
@ -42,32 +42,32 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
%HasMany{
cardinality: :many,
destination: Tabloid,
destination_field: :post_id,
destination_attribute: :post_id,
name: :unrelated_posts_join_assoc,
source: ManyToManyTest.Post,
source_field: :id,
source_attribute: :id,
type: :has_many,
private?: true
},
%HasMany{
cardinality: :many,
destination: SomeResource,
destination_field: :post_id,
destination_attribute: :post_id,
name: :related_posts_join_assoc,
source: ManyToManyTest.Post,
source_field: :id,
source_attribute: :id,
type: :has_many,
private?: true
},
%ManyToMany{
cardinality: :many,
destination: ManyToManyTest.Post,
destination_field: :id,
destination_field_on_join_table: :related_post_id,
destination_attribute: :id,
destination_attribute_on_join_resource: :related_post_id,
name: :related_posts,
source: ManyToManyTest.Post,
source_field: :id,
source_field_on_join_table: :post_id,
source_attribute: :id,
source_attribute_on_join_resource: :post_id,
through: SomeResource,
type: :many_to_many,
private?: false
@ -75,12 +75,12 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
%ManyToMany{
cardinality: :many,
destination: ManyToManyTest.Post,
destination_field: :id,
destination_field_on_join_table: :unrelated_post_id,
destination_attribute: :id,
destination_attribute_on_join_resource: :unrelated_post_id,
name: :unrelated_posts,
source: ManyToManyTest.Post,
source_field: :id,
source_field_on_join_table: :post_id,
source_attribute: :id,
source_attribute_on_join_resource: :post_id,
through: Tabloid,
type: :many_to_many,
private?: true
@ -108,8 +108,8 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
relationships do
many_to_many :foobars, Foobar,
through: "some_table",
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end
end
@ -121,76 +121,76 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
relationships do
many_to_many :foobars, Foobar,
through: FooBars,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end
end
test "it fails if you dont pass an atom for `source_field_on_join_table`" do
test "it fails if you dont pass an atom for `source_attribute_on_join_resource`" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :source_field_on_join_table to be an atom, got: \"what\"",
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :source_attribute_on_join_resource to be an atom, got: \"what\"",
fn ->
defposts do
relationships do
many_to_many :foobars, Foobar,
through: FooBars,
source_field_on_join_table: "what",
destination_field_on_join_table: :destination_post_id
source_attribute_on_join_resource: "what",
destination_attribute_on_join_resource: :destination_post_id
end
end
end
)
end
test "it fails if you dont pass an atom for `destination_field_on_join_table`" do
test "it fails if you dont pass an atom for `destination_attribute_on_join_resource`" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :destination_field_on_join_table to be an atom, got: \"what\"",
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :destination_attribute_on_join_resource to be an atom, got: \"what\"",
fn ->
defposts do
relationships do
many_to_many :foobars, Foobar,
through: FooBar,
destination_field_on_join_table: "what",
source_field_on_join_table: :source_post_id
destination_attribute_on_join_resource: "what",
source_attribute_on_join_resource: :source_post_id
end
end
end
)
end
test "it fails if you dont pass an atom for `source_field`" do
test "it fails if you dont pass an atom for `source_attribute`" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :source_field to be an atom, got: \"what\"",
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :source_attribute to be an atom, got: \"what\"",
fn ->
defposts do
relationships do
many_to_many :foobars, Foobar,
through: FooBar,
source_field: "what",
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
source_attribute: "what",
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end
end
)
end
test "it fails if you dont pass an atom for `destination_field`" do
test "it fails if you dont pass an atom for `destination_attribute`" do
assert_raise(
Spark.Error.DslError,
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :destination_field to be an atom, got: \"what\"",
"[Ash.Test.Resource.Relationships.ManyToManyTest.Post]\n relationships -> many_to_many -> foobars:\n expected :destination_attribute to be an atom, got: \"what\"",
fn ->
defposts do
relationships do
many_to_many :foobars, Foobar,
through: FooBars,
destination_field: "what",
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id
destination_attribute: "what",
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id
end
end
end
@ -206,8 +206,8 @@ defmodule Ash.Test.Resource.Relationships.ManyToManyTest do
relationships do
many_to_many :foobars, Foobar,
through: FooBars,
source_field_on_join_table: :source_post_id,
destination_field_on_join_table: :destination_post_id,
source_attribute_on_join_resource: :source_post_id,
destination_attribute_on_join_resource: :destination_post_id,
private?: "an_invalid_field"
end
end

View file

@ -24,10 +24,10 @@ defmodule Ash.Test.SeedTest do
end
relationships do
has_many :posts, Ash.Test.SeedTest.Post, destination_field: :author_id
has_many :posts, Ash.Test.SeedTest.Post, destination_attribute: :author_id
has_one :latest_post, Ash.Test.SeedTest.Post,
destination_field: :author_id,
destination_attribute: :author_id,
sort: [inserted_at: :desc]
end
end
@ -61,8 +61,8 @@ defmodule Ash.Test.SeedTest do
many_to_many :categories, Ash.Test.SeedTest.Category,
through: Ash.Test.SeedTest.PostCategory,
destination_field_on_join_table: :category_id,
source_field_on_join_table: :post_id
destination_attribute_on_join_resource: :category_id,
source_attribute_on_join_resource: :post_id
end
end
@ -107,8 +107,8 @@ defmodule Ash.Test.SeedTest do
relationships do
many_to_many :posts, Post,
through: PostCategory,
destination_field_on_join_table: :post_id,
source_field_on_join_table: :category_id
destination_attribute_on_join_resource: :post_id,
source_attribute_on_join_resource: :category_id
end
end

View file

@ -17,7 +17,7 @@ defmodule Ash.Test.Support.PolicyRbac.Organization do
relationships do
has_many :memberships, Ash.Test.Support.PolicyRbac.Membership do
destination_field(:organization_id)
destination_attribute(:organization_id)
end
end
end

View file

@ -19,7 +19,7 @@ defmodule Ash.Test.Support.PolicyRbac.User do
end
relationships do
has_many(:memberships, Ash.Test.Support.PolicyRbac.Membership, destination_field: :user_id)
has_many(:memberships, Ash.Test.Support.PolicyRbac.Membership, destination_attribute: :user_id)
belongs_to(:organization, Ash.Test.Support.PolicyRbac.Organization)
end

View file

@ -31,8 +31,8 @@ defmodule Ash.Test.Support.PolicySimple.Car do
relationships do
many_to_many :users, Ash.Test.Support.PolicySimple.User do
through(Ash.Test.Support.PolicySimple.CarUser)
source_field_on_join_table(:car_id)
destination_field_on_join_table(:user_id)
source_attribute_on_join_resource(:car_id)
destination_attribute_on_join_resource(:user_id)
end
end
end

View file

@ -32,12 +32,12 @@ defmodule Ash.Test.Support.PolicySimple.User do
relationships do
belongs_to(:organization, Ash.Test.Support.PolicySimple.Organization)
has_many(:posts, Ash.Test.Support.PolicySimple.Post, destination_field: :author_id)
has_many(:posts, Ash.Test.Support.PolicySimple.Post, destination_attribute: :author_id)
many_to_many :cars, Ash.Test.Support.PolicySimple.Car do
through(Ash.Test.Support.PolicySimple.CarUser)
source_field_on_join_table(:user_id)
destination_field_on_join_table(:car_id)
source_attribute_on_join_resource(:user_id)
destination_attribute_on_join_resource(:car_id)
end
end
end