mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
improvement: support select_by_default?
flag on attributes
This commit is contained in:
parent
0f31d463d9
commit
e33dc23a07
19 changed files with 117 additions and 63 deletions
|
@ -187,6 +187,7 @@ spark_locals_without_parens = [
|
||||||
resource: 1,
|
resource: 1,
|
||||||
resource: 2,
|
resource: 2,
|
||||||
run: 1,
|
run: 1,
|
||||||
|
select_by_default?: 1,
|
||||||
sensitive?: 1,
|
sensitive?: 1,
|
||||||
short_name: 1,
|
short_name: 1,
|
||||||
skip_global_validations?: 1,
|
skip_global_validations?: 1,
|
||||||
|
|
|
@ -89,6 +89,7 @@ end
|
||||||
| [`description`](#attributes-attribute-description){: #attributes-attribute-description } | `String.t` | | An optional description for the attribute. |
|
| [`description`](#attributes-attribute-description){: #attributes-attribute-description } | `String.t` | | An optional description for the attribute. |
|
||||||
| [`sensitive?`](#attributes-attribute-sensitive?){: #attributes-attribute-sensitive? } | `boolean` | `false` | Whether or not the attribute value contains sensitive information, like PII(Personally Identifiable Information). See the [Sensitive Data guide](/documentation/topics/security/sensitive-data.md) for more. |
|
| [`sensitive?`](#attributes-attribute-sensitive?){: #attributes-attribute-sensitive? } | `boolean` | `false` | Whether or not the attribute value contains sensitive information, like PII(Personally Identifiable Information). See the [Sensitive Data guide](/documentation/topics/security/sensitive-data.md) for more. |
|
||||||
| [`source`](#attributes-attribute-source){: #attributes-attribute-source } | `atom` | | If the field should be mapped to a different name in the data layer. Support varies by data layer. |
|
| [`source`](#attributes-attribute-source){: #attributes-attribute-source } | `atom` | | If the field should be mapped to a different name in the data layer. Support varies by data layer. |
|
||||||
|
| [`select_by_default?`](#attributes-attribute-select_by_default?){: #attributes-attribute-select_by_default? } | `boolean` | `true` | Whether or not the attribute is selected by default. |
|
||||||
| [`always_select?`](#attributes-attribute-always_select?){: #attributes-attribute-always_select? } | `boolean` | `false` | Whether or not to ensure this attribute is always selected when reading from the database, regardless of applied select statements. |
|
| [`always_select?`](#attributes-attribute-always_select?){: #attributes-attribute-always_select? } | `boolean` | `false` | Whether or not to ensure this attribute is always selected when reading from the database, regardless of applied select statements. |
|
||||||
| [`primary_key?`](#attributes-attribute-primary_key?){: #attributes-attribute-primary_key? } | `boolean` | `false` | Whether the attribute is the primary key. Composite primary key is also possible by using `primary_key? true` in more than one attribute. If primary_key? is true, allow_nil? must be false. |
|
| [`primary_key?`](#attributes-attribute-primary_key?){: #attributes-attribute-primary_key? } | `boolean` | `false` | Whether the attribute is the primary key. Composite primary key is also possible by using `primary_key? true` in more than one attribute. If primary_key? is true, allow_nil? must be false. |
|
||||||
| [`allow_nil?`](#attributes-attribute-allow_nil?){: #attributes-attribute-allow_nil? } | `boolean` | `true` | Whether or not the attribute can be set to nil. If nil value is given error is raised. |
|
| [`allow_nil?`](#attributes-attribute-allow_nil?){: #attributes-attribute-allow_nil? } | `boolean` | `true` | Whether or not the attribute can be set to nil. If nil value is given error is raised. |
|
||||||
|
|
|
@ -782,11 +782,15 @@ defmodule Ash.Actions.Helpers do
|
||||||
resource
|
resource
|
||||||
|> Ash.Resource.Info.attributes()
|
|> Ash.Resource.Info.attributes()
|
||||||
|> Enum.flat_map(fn attribute ->
|
|> Enum.flat_map(fn attribute ->
|
||||||
|
if is_nil(select) do
|
||||||
|
attribute.select_by_default?
|
||||||
|
else
|
||||||
if attribute.always_select? || attribute.primary_key? || attribute.name in select do
|
if attribute.always_select? || attribute.primary_key? || attribute.name in select do
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
[attribute.name]
|
[attribute.name]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|> Enum.reduce(result, fn key, record ->
|
|> Enum.reduce(result, fn key, record ->
|
||||||
record
|
record
|
||||||
|
@ -804,22 +808,4 @@ defmodule Ash.Actions.Helpers do
|
||||||
results
|
results
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def attributes_to_select(%{select: nil, resource: resource}) do
|
|
||||||
resource
|
|
||||||
|> Ash.Resource.Info.attributes()
|
|
||||||
|> Enum.map(& &1.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def attributes_to_select(%{select: select, resource: resource}) do
|
|
||||||
resource
|
|
||||||
|> Ash.Resource.Info.attributes()
|
|
||||||
|> Enum.flat_map(fn attribute ->
|
|
||||||
if attribute.always_select? || attribute.primary_key? || attribute.name in select do
|
|
||||||
[attribute.name]
|
|
||||||
else
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -898,12 +898,10 @@ defmodule Ash.Actions.Read do
|
||||||
if query.select do
|
if query.select do
|
||||||
query
|
query
|
||||||
else
|
else
|
||||||
to_select =
|
Ash.Query.select(
|
||||||
query.resource
|
query,
|
||||||
|> Ash.Resource.Info.attributes()
|
Ash.Resource.Info.selected_by_default_attribute_names(query.resource)
|
||||||
|> Enum.map(& &1.name)
|
)
|
||||||
|
|
||||||
Ash.Query.select(query, to_select)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -438,11 +438,23 @@ defmodule Ash.Changeset do
|
||||||
"""
|
"""
|
||||||
def select(changeset, fields, opts \\ []) do
|
def select(changeset, fields, opts \\ []) do
|
||||||
if opts[:replace?] do
|
if opts[:replace?] do
|
||||||
%{changeset | select: Enum.uniq(List.wrap(fields))}
|
case fields do
|
||||||
|
%MapSet{} = fields -> %{changeset | select: Enum.to_list(fields)}
|
||||||
|
fields -> %{changeset | select: Enum.uniq(List.wrap(fields))}
|
||||||
|
end
|
||||||
else
|
else
|
||||||
|
case fields do
|
||||||
|
%MapSet{} ->
|
||||||
|
%{
|
||||||
|
changeset
|
||||||
|
| select: MapSet.union(MapSet.new(changeset.select), fields) |> MapSet.to_list()
|
||||||
|
}
|
||||||
|
|
||||||
|
fields ->
|
||||||
%{changeset | select: Enum.uniq(List.wrap(fields) ++ (changeset.select || []))}
|
%{changeset | select: Enum.uniq(List.wrap(fields) ++ (changeset.select || []))}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Calls the provided load statement on the result of the action at the very end of the action.
|
Calls the provided load statement on the result of the action at the very end of the action.
|
||||||
|
@ -476,10 +488,7 @@ defmodule Ash.Changeset do
|
||||||
if changeset.select do
|
if changeset.select do
|
||||||
Ash.Changeset.select(changeset, List.wrap(fields))
|
Ash.Changeset.select(changeset, List.wrap(fields))
|
||||||
else
|
else
|
||||||
to_select =
|
to_select = Ash.Resource.Info.selected_by_default_attribute_names(changeset.resource)
|
||||||
changeset.resource
|
|
||||||
|> Ash.Resource.Info.attributes()
|
|
||||||
|> Enum.map(& &1.name)
|
|
||||||
|
|
||||||
Ash.Changeset.select(changeset, to_select)
|
Ash.Changeset.select(changeset, to_select)
|
||||||
end
|
end
|
||||||
|
|
|
@ -844,9 +844,14 @@ defmodule Ash.Query do
|
||||||
Use `ensure_selected/2` if you wish to make sure a field has been selected, without deselecting any other fields.
|
Use `ensure_selected/2` if you wish to make sure a field has been selected, without deselecting any other fields.
|
||||||
"""
|
"""
|
||||||
def select(query, fields, opts \\ []) do
|
def select(query, fields, opts \\ []) do
|
||||||
|
fields =
|
||||||
|
case fields do
|
||||||
|
%MapSet{} = fields -> fields
|
||||||
|
fields -> MapSet.new(List.wrap(fields))
|
||||||
|
end
|
||||||
|
|
||||||
query = new(query)
|
query = new(query)
|
||||||
existing_fields = Ash.Resource.Info.attribute_names(query.resource)
|
existing_fields = Ash.Resource.Info.attribute_names(query.resource)
|
||||||
fields = MapSet.new(List.wrap(fields))
|
|
||||||
|
|
||||||
valid_fields = MapSet.intersection(fields, existing_fields)
|
valid_fields = MapSet.intersection(fields, existing_fields)
|
||||||
|
|
||||||
|
@ -863,16 +868,16 @@ defmodule Ash.Query do
|
||||||
query
|
query
|
||||||
end
|
end
|
||||||
|
|
||||||
always_select =
|
select =
|
||||||
valid_fields
|
valid_fields
|
||||||
|> MapSet.union(Ash.Resource.Info.always_selected_attribute_names(query.resource))
|
|> MapSet.union(Ash.Resource.Info.always_selected_attribute_names(query.resource))
|
||||||
|> MapSet.union(MapSet.new(Ash.Resource.Info.primary_key(query.resource)))
|
|> MapSet.union(MapSet.new(Ash.Resource.Info.primary_key(query.resource)))
|
||||||
|
|
||||||
new_select =
|
new_select =
|
||||||
if opts[:replace?] do
|
if opts[:replace?] do
|
||||||
always_select
|
select
|
||||||
else
|
else
|
||||||
MapSet.union(MapSet.new(query.select || []), always_select)
|
MapSet.union(MapSet.new(query.select || []), select)
|
||||||
end
|
end
|
||||||
|
|
||||||
%{query | select: MapSet.to_list(new_select)}
|
%{query | select: MapSet.to_list(new_select)}
|
||||||
|
@ -1021,10 +1026,7 @@ defmodule Ash.Query do
|
||||||
if query.select do
|
if query.select do
|
||||||
Ash.Query.select(query, List.wrap(fields))
|
Ash.Query.select(query, List.wrap(fields))
|
||||||
else
|
else
|
||||||
to_select =
|
to_select = Ash.Resource.Info.selected_by_default_attribute_names(query.resource)
|
||||||
query.resource
|
|
||||||
|> Ash.Resource.Info.attributes()
|
|
||||||
|> Enum.map(& &1.name)
|
|
||||||
|
|
||||||
Ash.Query.select(query, to_select)
|
Ash.Query.select(query, to_select)
|
||||||
end
|
end
|
||||||
|
@ -1063,22 +1065,26 @@ defmodule Ash.Query do
|
||||||
|
|
||||||
select =
|
select =
|
||||||
if query.select do
|
if query.select do
|
||||||
query.select
|
query.select -- List.wrap(fields)
|
||||||
else
|
else
|
||||||
query.resource
|
MapSet.difference(
|
||||||
|> Ash.Resource.Info.attributes()
|
Ash.Resource.Info.selected_by_default_attribute_names(query.resource),
|
||||||
|> Enum.map(& &1.name)
|
MapSet.new(List.wrap(fields))
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
select = select -- List.wrap(fields)
|
|
||||||
|
|
||||||
select(query, select, replace?: true)
|
select(query, select, replace?: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def selecting?(query, field) do
|
def selecting?(query, field) do
|
||||||
case query.select do
|
case query.select do
|
||||||
nil ->
|
nil ->
|
||||||
not is_nil(Ash.Resource.Info.attribute(query.resource, field))
|
query.resource
|
||||||
|
|> Ash.Resource.Info.attribute(field)
|
||||||
|
|> case do
|
||||||
|
%{select_by_default?: true} -> true
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
|
||||||
select ->
|
select ->
|
||||||
if field in select do
|
if field in select do
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Ash.Resource.Attribute do
|
||||||
:public?,
|
:public?,
|
||||||
:writable?,
|
:writable?,
|
||||||
:always_select?,
|
:always_select?,
|
||||||
|
:select_by_default?,
|
||||||
:default,
|
:default,
|
||||||
:update_default,
|
:update_default,
|
||||||
:description,
|
:description,
|
||||||
|
@ -39,6 +40,7 @@ defmodule Ash.Resource.Attribute do
|
||||||
primary_key?: boolean(),
|
primary_key?: boolean(),
|
||||||
public?: boolean(),
|
public?: boolean(),
|
||||||
sortable?: boolean(),
|
sortable?: boolean(),
|
||||||
|
select_by_default?: boolean(),
|
||||||
default: nil | term | (-> term),
|
default: nil | term | (-> term),
|
||||||
update_default: nil | term | (-> term) | (Ash.Resource.record() -> term),
|
update_default: nil | term | (-> term) | (Ash.Resource.record() -> term),
|
||||||
sensitive?: boolean(),
|
sensitive?: boolean(),
|
||||||
|
@ -79,6 +81,13 @@ defmodule Ash.Resource.Attribute do
|
||||||
If the field should be mapped to a different name in the data layer. Support varies by data layer.
|
If the field should be mapped to a different name in the data layer. Support varies by data layer.
|
||||||
"""
|
"""
|
||||||
],
|
],
|
||||||
|
select_by_default?: [
|
||||||
|
type: :boolean,
|
||||||
|
default: true,
|
||||||
|
doc: """
|
||||||
|
Whether or not the attribute is selected by default.
|
||||||
|
"""
|
||||||
|
],
|
||||||
always_select?: [
|
always_select?: [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -1496,6 +1496,7 @@ defmodule Ash.Resource.Dsl do
|
||||||
Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch,
|
Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch,
|
||||||
Ash.Resource.Verifiers.VerifyReservedCalculationArguments,
|
Ash.Resource.Verifiers.VerifyReservedCalculationArguments,
|
||||||
Ash.Resource.Verifiers.VerifyIdentityFields,
|
Ash.Resource.Verifiers.VerifyIdentityFields,
|
||||||
|
Ash.Resource.Verifiers.VerifySelectedByDefault,
|
||||||
Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation,
|
Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation,
|
||||||
Ash.Resource.Verifiers.ValidateRelationshipAttributes,
|
Ash.Resource.Verifiers.ValidateRelationshipAttributes,
|
||||||
Ash.Resource.Verifiers.NoReservedFieldNames,
|
Ash.Resource.Verifiers.NoReservedFieldNames,
|
||||||
|
|
|
@ -5,7 +5,7 @@ defmodule Ash.Resource.Igniter do
|
||||||
def list_resources(igniter) do
|
def list_resources(igniter) do
|
||||||
Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
|
Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
|
||||||
zipper
|
zipper
|
||||||
|> Igniter.Code.Module.move_to_use(resource_mods())
|
|> Igniter.Code.Module.move_to_use(resource_mods(igniter))
|
||||||
|> case do
|
|> case do
|
||||||
{:ok, _} ->
|
{:ok, _} ->
|
||||||
true
|
true
|
||||||
|
@ -24,7 +24,7 @@ defmodule Ash.Resource.Igniter do
|
||||||
{:ok, {igniter, _source, zipper}} ->
|
{:ok, {igniter, _source, zipper}} ->
|
||||||
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
|
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
|
||||||
{:ok, zipper} <-
|
{:ok, zipper} <-
|
||||||
Igniter.Code.Module.move_to_use(zipper, resource_mods()),
|
Igniter.Code.Module.move_to_use(zipper, resource_mods(igniter)),
|
||||||
{:ok, zipper} <-
|
{:ok, zipper} <-
|
||||||
Igniter.Code.Function.move_to_nth_argument(zipper, 1),
|
Igniter.Code.Function.move_to_nth_argument(zipper, 1),
|
||||||
{:ok, zipper} <- Igniter.Code.Keyword.get_key(zipper, :domain),
|
{:ok, zipper} <- Igniter.Code.Keyword.get_key(zipper, :domain),
|
||||||
|
@ -41,8 +41,8 @@ defmodule Ash.Resource.Igniter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_mods do
|
def resource_mods(igniter) do
|
||||||
app_name = Igniter.Project.Application.app_name()
|
app_name = Igniter.Project.Application.app_name(igniter)
|
||||||
|
|
||||||
[Ash.Resource | List.wrap(Application.get_env(app_name, :base_resources))]
|
[Ash.Resource | List.wrap(Application.get_env(app_name, :base_resources))]
|
||||||
end
|
end
|
||||||
|
|
|
@ -779,6 +779,11 @@ defmodule Ash.Resource.Info do
|
||||||
Extension.get_persisted(resource, :always_selected_attribute_names)
|
Extension.get_persisted(resource, :always_selected_attribute_names)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec selected_by_default_attribute_names(Spark.Dsl.t() | Ash.Resource.t()) :: MapSet.t()
|
||||||
|
def selected_by_default_attribute_names(resource) do
|
||||||
|
Extension.get_persisted(resource, :selected_by_default_attribute_names)
|
||||||
|
end
|
||||||
|
|
||||||
@doc "Returns all attributes, aggregates, calculations and relationships of a resource"
|
@doc "Returns all attributes, aggregates, calculations and relationships of a resource"
|
||||||
@spec fields(
|
@spec fields(
|
||||||
Spark.Dsl.t() | Ash.Resource.t(),
|
Spark.Dsl.t() | Ash.Resource.t(),
|
||||||
|
|
|
@ -66,12 +66,18 @@ defmodule Ash.Resource.Transformers.AttributesByName do
|
||||||
|> Enum.map(& &1.name)
|
|> Enum.map(& &1.name)
|
||||||
|> MapSet.new()
|
|> MapSet.new()
|
||||||
|
|
||||||
|
selected_by_default_attribute_names =
|
||||||
|
Enum.filter(attributes, & &1.select_by_default?)
|
||||||
|
|> Enum.map(& &1.name)
|
||||||
|
|> MapSet.new()
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
persist(
|
persist(
|
||||||
dsl_state,
|
dsl_state,
|
||||||
%{
|
%{
|
||||||
attributes_by_name: attributes_by_name,
|
attributes_by_name: attributes_by_name,
|
||||||
attribute_names: attribute_names,
|
attribute_names: attribute_names,
|
||||||
|
selected_by_default_attribute_names: selected_by_default_attribute_names,
|
||||||
create_attributes_with_static_defaults: create_attributes_with_static_defaults,
|
create_attributes_with_static_defaults: create_attributes_with_static_defaults,
|
||||||
create_attributes_with_non_matching_lazy_defaults:
|
create_attributes_with_non_matching_lazy_defaults:
|
||||||
create_attributes_with_non_matching_lazy_defaults,
|
create_attributes_with_non_matching_lazy_defaults,
|
||||||
|
|
30
lib/ash/resource/verifiers/verify_selected_by_default.ex
Normal file
30
lib/ash/resource/verifiers/verify_selected_by_default.ex
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
defmodule Ash.Resource.Verifiers.VerifySelectedByDefault do
|
||||||
|
@moduledoc """
|
||||||
|
Raises an error when a required primary key is missing
|
||||||
|
"""
|
||||||
|
use Spark.Dsl.Verifier
|
||||||
|
alias Spark.Dsl.Verifier
|
||||||
|
|
||||||
|
def verify(dsl) do
|
||||||
|
resource = Verifier.get_persisted(dsl, :module)
|
||||||
|
data_layer = Ash.DataLayer.data_layer(resource)
|
||||||
|
|
||||||
|
if is_nil(data_layer) || data_layer.can?(resource, :select) do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
Enum.each(Ash.Resource.Info.attributes(dsl), fn attribute ->
|
||||||
|
if !attribute.select_by_default? do
|
||||||
|
raise Spark.Error.DslError,
|
||||||
|
module: resource,
|
||||||
|
path: [:attributes, attribute.name],
|
||||||
|
message: """
|
||||||
|
Attribute #{inspect(resource)}.#{attribute.name} was marked with `select_by_default: false`,
|
||||||
|
but the data layer #{inspect(data_layer)} does not support selecting attributes.
|
||||||
|
|
||||||
|
This means that all attributes will always be selected.
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,7 +18,7 @@ defmodule Mix.Tasks.Ash.Gen.BaseResource do
|
||||||
|
|
||||||
glob = Path.join([base_resource_file, "..", "**", "*.ex"])
|
glob = Path.join([base_resource_file, "..", "**", "*.ex"])
|
||||||
|
|
||||||
app_name = Igniter.Project.Application.app_name()
|
app_name = Igniter.Project.Application.app_name(igniter)
|
||||||
|
|
||||||
# need `Igniter.glob(igniter, path, filter)` to get all existing or new files that match a path & condition
|
# need `Igniter.glob(igniter, path, filter)` to get all existing or new files that match a path & condition
|
||||||
# for each file that defines a resource that uses `Ash.Resource`, that is "further down" from this file,
|
# for each file that defines a resource that uses `Ash.Resource`, that is "further down" from this file,
|
||||||
|
|
|
@ -28,7 +28,7 @@ defmodule Mix.Tasks.Ash.Gen.Domain do
|
||||||
|
|
||||||
domain_file = Igniter.Code.Module.proper_location(domain)
|
domain_file = Igniter.Code.Module.proper_location(domain)
|
||||||
|
|
||||||
app_name = Igniter.Project.Application.app_name()
|
app_name = Igniter.Project.Application.app_name(igniter)
|
||||||
|
|
||||||
if "--ignore-if-exists" in argv && Igniter.exists?(igniter, domain_file) do
|
if "--ignore-if-exists" in argv && Igniter.exists?(igniter, domain_file) do
|
||||||
igniter
|
igniter
|
||||||
|
|
|
@ -72,7 +72,7 @@ defmodule Mix.Tasks.Ash.Gen.Resource do
|
||||||
def igniter(igniter, argv) do
|
def igniter(igniter, argv) do
|
||||||
{%{resource: resource}, argv} = positional_args!(argv)
|
{%{resource: resource}, argv} = positional_args!(argv)
|
||||||
resource = Igniter.Code.Module.parse(resource)
|
resource = Igniter.Code.Module.parse(resource)
|
||||||
app_name = Igniter.Project.Application.app_name()
|
app_name = Igniter.Project.Application.app_name(igniter)
|
||||||
|
|
||||||
options = options!(argv)
|
options = options!(argv)
|
||||||
|
|
||||||
|
|
|
@ -81,10 +81,12 @@ defmodule Mix.Tasks.Ash.Install do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp generate_example(igniter, argv) do
|
defp generate_example(igniter, argv) do
|
||||||
domain_module_name = Igniter.Code.Module.module_name("Support")
|
domain_module_name = Igniter.Code.Module.module_name(igniter, "Support")
|
||||||
ticket_resource = Igniter.Code.Module.module_name("Support.Ticket")
|
ticket_resource = Igniter.Code.Module.module_name(igniter, "Support.Ticket")
|
||||||
representative_resource = Igniter.Code.Module.module_name("Support.Representative")
|
representative_resource = Igniter.Code.Module.module_name(igniter, "Support.Representative")
|
||||||
ticket_status_module_name = Igniter.Code.Module.module_name("Support.Ticket.Types.Status")
|
|
||||||
|
ticket_status_module_name =
|
||||||
|
Igniter.Code.Module.module_name(igniter, "Support.Ticket.Types.Status")
|
||||||
|
|
||||||
igniter
|
igniter
|
||||||
|> Igniter.compose_task("ash.gen.domain", [inspect(domain_module_name)])
|
|> Igniter.compose_task("ash.gen.domain", [inspect(domain_module_name)])
|
||||||
|
|
2
mix.exs
2
mix.exs
|
@ -360,7 +360,7 @@ defmodule Ash.MixProject do
|
||||||
{:simple_sat, "~> 0.1 and >= 0.1.1", optional: true},
|
{:simple_sat, "~> 0.1 and >= 0.1.1", optional: true},
|
||||||
|
|
||||||
# Code Generators
|
# Code Generators
|
||||||
{:igniter, "~> 0.3 and >= 0.3.11"},
|
{:igniter, "~> 0.3 and >= 0.3.33"},
|
||||||
|
|
||||||
# IO Utilities
|
# IO Utilities
|
||||||
{:owl, "~> 0.11"},
|
{:owl, "~> 0.11"},
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -18,7 +18,7 @@
|
||||||
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
|
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
|
||||||
"git_ops": {:hex, :git_ops, "2.6.1", "cc7799a68c26cf814d6d1a5121415b4f5bf813de200908f930b27a2f1fe9dad5", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "ce62d07e41fe993ec22c35d5edb11cf333a21ddaead6f5d9868fcb607d42039e"},
|
"git_ops": {:hex, :git_ops, "2.6.1", "cc7799a68c26cf814d6d1a5121415b4f5bf813de200908f930b27a2f1fe9dad5", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "ce62d07e41fe993ec22c35d5edb11cf333a21ddaead6f5d9868fcb607d42039e"},
|
||||||
"glob_ex": {:hex, :glob_ex, "0.1.8", "f7ef872877ca2ae7a792ab1f9ff73d9c16bf46ecb028603a8a3c5283016adc07", [:mix], [], "hexpm", "9e39d01729419a60a937c9260a43981440c43aa4cadd1fa6672fecd58241c464"},
|
"glob_ex": {:hex, :glob_ex, "0.1.8", "f7ef872877ca2ae7a792ab1f9ff73d9c16bf46ecb028603a8a3c5283016adc07", [:mix], [], "hexpm", "9e39d01729419a60a937c9260a43981440c43aa4cadd1fa6672fecd58241c464"},
|
||||||
"igniter": {:hex, :igniter, "0.3.25", "cce36fd49b499d215d0605ee3bfeb8fabe2f86b70b2df24ef3a50797409bceee", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:rewrite, "~> 0.9", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "ffccb3c03cfdc8694be27a4c1d5615799ac140c27f32c74d1817171c4d411a62"},
|
"igniter": {:hex, :igniter, "0.3.34", "fee93422583884b4a6985de45797097d36f36283d4e61c6154d0e8ec02e19e2b", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:rewrite, "~> 0.9", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "b8e0bd0cdc8354b44f292a3eab4eaac155e4a9c9784b066ec29a2587595bcae8"},
|
||||||
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
|
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
|
||||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||||
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
|
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
"simple_sat": {:hex, :simple_sat, "0.1.3", "f650fc3c184a5fe741868b5ac56dc77fdbb428468f6dbf1978e14d0334497578", [:mix], [], "hexpm", "a54305066a356b7194dc81db2a89232bacdc0b3edaef68ed9aba28dcbc34887b"},
|
"simple_sat": {:hex, :simple_sat, "0.1.3", "f650fc3c184a5fe741868b5ac56dc77fdbb428468f6dbf1978e14d0334497578", [:mix], [], "hexpm", "a54305066a356b7194dc81db2a89232bacdc0b3edaef68ed9aba28dcbc34887b"},
|
||||||
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
|
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
|
||||||
"sourceror": {:hex, :sourceror, "1.6.0", "9907884e1449a4bd7dbaabe95088ed4d9a09c3c791fb0103964e6316bc9448a7", [:mix], [], "hexpm", "e90aef8c82dacf32c89c8ef83d1416fc343cd3e5556773eeffd2c1e3f991f699"},
|
"sourceror": {:hex, :sourceror, "1.6.0", "9907884e1449a4bd7dbaabe95088ed4d9a09c3c791fb0103964e6316bc9448a7", [:mix], [], "hexpm", "e90aef8c82dacf32c89c8ef83d1416fc343cd3e5556773eeffd2c1e3f991f699"},
|
||||||
"spark": {:hex, :spark, "2.2.24", "0cbd0e224af530f8f12f0e83ac5743b21802fb821d85b58d32a4da7e2268522b", [:mix], [{:igniter, ">= 0.2.6 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "f05fd64ef74b3f3fe7817743962956dcc8a8e84bb9dc796ac7bf7fdcf4db5b6d"},
|
"spark": {:hex, :spark, "2.2.26", "1701f388a9cfb2e27cd037b6f4b72a999e49bdb2d2f946bdbde8a991ce42c499", [:mix], [{:igniter, ">= 0.2.6 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "7a57860e4d15ab2e395dffeac617f3ee64d371b47f7b3d718a8d535d75cc7556"},
|
||||||
"spitfire": {:hex, :spitfire, "0.1.3", "7ea0f544005dfbe48e615ed90250c9a271bfe126914012023fd5e4b6b82b7ec7", [:mix], [], "hexpm", "d53b5107bcff526a05c5bb54c95e77b36834550affd5830c9f58760e8c543657"},
|
"spitfire": {:hex, :spitfire, "0.1.3", "7ea0f544005dfbe48e615ed90250c9a271bfe126914012023fd5e4b6b82b7ec7", [:mix], [], "hexpm", "d53b5107bcff526a05c5bb54c95e77b36834550affd5830c9f58760e8c543657"},
|
||||||
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
|
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
|
||||||
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
|
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
|
||||||
|
|
|
@ -613,7 +613,7 @@ defmodule Ash.Test.Actions.ReadTest do
|
||||||
|> strip_metadata()
|
|> strip_metadata()
|
||||||
end
|
end
|
||||||
|
|
||||||
test "a sort will sor rows accordingly when descending", %{
|
test "a sort will sort rows accordingly when descending", %{
|
||||||
post1: post1,
|
post1: post1,
|
||||||
post2: post2
|
post2: post2
|
||||||
} do
|
} do
|
||||||
|
|
Loading…
Reference in a new issue