mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 21:13:10 +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: 2,
|
||||
run: 1,
|
||||
select_by_default?: 1,
|
||||
sensitive?: 1,
|
||||
short_name: 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. |
|
||||
| [`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. |
|
||||
| [`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. |
|
||||
| [`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. |
|
||||
|
|
|
@ -782,11 +782,15 @@ defmodule Ash.Actions.Helpers do
|
|||
resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> 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
|
||||
[]
|
||||
else
|
||||
[attribute.name]
|
||||
end
|
||||
end
|
||||
end)
|
||||
|> Enum.reduce(result, fn key, record ->
|
||||
record
|
||||
|
@ -804,22 +808,4 @@ defmodule Ash.Actions.Helpers do
|
|||
results
|
||||
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
|
||||
|
|
|
@ -898,12 +898,10 @@ defmodule Ash.Actions.Read do
|
|||
if query.select do
|
||||
query
|
||||
else
|
||||
to_select =
|
||||
query.resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.map(& &1.name)
|
||||
|
||||
Ash.Query.select(query, to_select)
|
||||
Ash.Query.select(
|
||||
query,
|
||||
Ash.Resource.Info.selected_by_default_attribute_names(query.resource)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -438,11 +438,23 @@ defmodule Ash.Changeset do
|
|||
"""
|
||||
def select(changeset, fields, opts \\ []) 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
|
||||
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 || []))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
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
|
||||
Ash.Changeset.select(changeset, List.wrap(fields))
|
||||
else
|
||||
to_select =
|
||||
changeset.resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.map(& &1.name)
|
||||
to_select = Ash.Resource.Info.selected_by_default_attribute_names(changeset.resource)
|
||||
|
||||
Ash.Changeset.select(changeset, to_select)
|
||||
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.
|
||||
"""
|
||||
def select(query, fields, opts \\ []) do
|
||||
fields =
|
||||
case fields do
|
||||
%MapSet{} = fields -> fields
|
||||
fields -> MapSet.new(List.wrap(fields))
|
||||
end
|
||||
|
||||
query = new(query)
|
||||
existing_fields = Ash.Resource.Info.attribute_names(query.resource)
|
||||
fields = MapSet.new(List.wrap(fields))
|
||||
|
||||
valid_fields = MapSet.intersection(fields, existing_fields)
|
||||
|
||||
|
@ -863,16 +868,16 @@ defmodule Ash.Query do
|
|||
query
|
||||
end
|
||||
|
||||
always_select =
|
||||
select =
|
||||
valid_fields
|
||||
|> MapSet.union(Ash.Resource.Info.always_selected_attribute_names(query.resource))
|
||||
|> MapSet.union(MapSet.new(Ash.Resource.Info.primary_key(query.resource)))
|
||||
|
||||
new_select =
|
||||
if opts[:replace?] do
|
||||
always_select
|
||||
select
|
||||
else
|
||||
MapSet.union(MapSet.new(query.select || []), always_select)
|
||||
MapSet.union(MapSet.new(query.select || []), select)
|
||||
end
|
||||
|
||||
%{query | select: MapSet.to_list(new_select)}
|
||||
|
@ -1021,10 +1026,7 @@ defmodule Ash.Query do
|
|||
if query.select do
|
||||
Ash.Query.select(query, List.wrap(fields))
|
||||
else
|
||||
to_select =
|
||||
query.resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.map(& &1.name)
|
||||
to_select = Ash.Resource.Info.selected_by_default_attribute_names(query.resource)
|
||||
|
||||
Ash.Query.select(query, to_select)
|
||||
end
|
||||
|
@ -1063,22 +1065,26 @@ defmodule Ash.Query do
|
|||
|
||||
select =
|
||||
if query.select do
|
||||
query.select
|
||||
query.select -- List.wrap(fields)
|
||||
else
|
||||
query.resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.map(& &1.name)
|
||||
MapSet.difference(
|
||||
Ash.Resource.Info.selected_by_default_attribute_names(query.resource),
|
||||
MapSet.new(List.wrap(fields))
|
||||
)
|
||||
end
|
||||
|
||||
select = select -- List.wrap(fields)
|
||||
|
||||
select(query, select, replace?: true)
|
||||
end
|
||||
|
||||
def selecting?(query, field) do
|
||||
case query.select do
|
||||
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 ->
|
||||
if field in select do
|
||||
|
|
|
@ -10,6 +10,7 @@ defmodule Ash.Resource.Attribute do
|
|||
:public?,
|
||||
:writable?,
|
||||
:always_select?,
|
||||
:select_by_default?,
|
||||
:default,
|
||||
:update_default,
|
||||
:description,
|
||||
|
@ -39,6 +40,7 @@ defmodule Ash.Resource.Attribute do
|
|||
primary_key?: boolean(),
|
||||
public?: boolean(),
|
||||
sortable?: boolean(),
|
||||
select_by_default?: boolean(),
|
||||
default: nil | term | (-> term),
|
||||
update_default: nil | term | (-> term) | (Ash.Resource.record() -> term),
|
||||
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.
|
||||
"""
|
||||
],
|
||||
select_by_default?: [
|
||||
type: :boolean,
|
||||
default: true,
|
||||
doc: """
|
||||
Whether or not the attribute is selected by default.
|
||||
"""
|
||||
],
|
||||
always_select?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
|
|
|
@ -1496,6 +1496,7 @@ defmodule Ash.Resource.Dsl do
|
|||
Ash.Resource.Verifiers.ValidateRelationshipAttributesMatch,
|
||||
Ash.Resource.Verifiers.VerifyReservedCalculationArguments,
|
||||
Ash.Resource.Verifiers.VerifyIdentityFields,
|
||||
Ash.Resource.Verifiers.VerifySelectedByDefault,
|
||||
Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation,
|
||||
Ash.Resource.Verifiers.ValidateRelationshipAttributes,
|
||||
Ash.Resource.Verifiers.NoReservedFieldNames,
|
||||
|
|
|
@ -5,7 +5,7 @@ defmodule Ash.Resource.Igniter do
|
|||
def list_resources(igniter) do
|
||||
Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
|
||||
zipper
|
||||
|> Igniter.Code.Module.move_to_use(resource_mods())
|
||||
|> Igniter.Code.Module.move_to_use(resource_mods(igniter))
|
||||
|> case do
|
||||
{:ok, _} ->
|
||||
true
|
||||
|
@ -24,7 +24,7 @@ defmodule Ash.Resource.Igniter do
|
|||
{:ok, {igniter, _source, zipper}} ->
|
||||
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
|
||||
{:ok, zipper} <-
|
||||
Igniter.Code.Module.move_to_use(zipper, resource_mods()),
|
||||
Igniter.Code.Module.move_to_use(zipper, resource_mods(igniter)),
|
||||
{:ok, zipper} <-
|
||||
Igniter.Code.Function.move_to_nth_argument(zipper, 1),
|
||||
{:ok, zipper} <- Igniter.Code.Keyword.get_key(zipper, :domain),
|
||||
|
@ -41,8 +41,8 @@ defmodule Ash.Resource.Igniter do
|
|||
end
|
||||
end
|
||||
|
||||
def resource_mods do
|
||||
app_name = Igniter.Project.Application.app_name()
|
||||
def resource_mods(igniter) do
|
||||
app_name = Igniter.Project.Application.app_name(igniter)
|
||||
|
||||
[Ash.Resource | List.wrap(Application.get_env(app_name, :base_resources))]
|
||||
end
|
||||
|
|
|
@ -779,6 +779,11 @@ defmodule Ash.Resource.Info do
|
|||
Extension.get_persisted(resource, :always_selected_attribute_names)
|
||||
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"
|
||||
@spec fields(
|
||||
Spark.Dsl.t() | Ash.Resource.t(),
|
||||
|
|
|
@ -66,12 +66,18 @@ defmodule Ash.Resource.Transformers.AttributesByName do
|
|||
|> Enum.map(& &1.name)
|
||||
|> MapSet.new()
|
||||
|
||||
selected_by_default_attribute_names =
|
||||
Enum.filter(attributes, & &1.select_by_default?)
|
||||
|> Enum.map(& &1.name)
|
||||
|> MapSet.new()
|
||||
|
||||
{:ok,
|
||||
persist(
|
||||
dsl_state,
|
||||
%{
|
||||
attributes_by_name: attributes_by_name,
|
||||
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_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"])
|
||||
|
||||
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
|
||||
# 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)
|
||||
|
||||
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
|
||||
igniter
|
||||
|
|
|
@ -72,7 +72,7 @@ defmodule Mix.Tasks.Ash.Gen.Resource do
|
|||
def igniter(igniter, argv) do
|
||||
{%{resource: resource}, argv} = positional_args!(argv)
|
||||
resource = Igniter.Code.Module.parse(resource)
|
||||
app_name = Igniter.Project.Application.app_name()
|
||||
app_name = Igniter.Project.Application.app_name(igniter)
|
||||
|
||||
options = options!(argv)
|
||||
|
||||
|
|
|
@ -81,10 +81,12 @@ defmodule Mix.Tasks.Ash.Install do
|
|||
end
|
||||
|
||||
defp generate_example(igniter, argv) do
|
||||
domain_module_name = Igniter.Code.Module.module_name("Support")
|
||||
ticket_resource = Igniter.Code.Module.module_name("Support.Ticket")
|
||||
representative_resource = Igniter.Code.Module.module_name("Support.Representative")
|
||||
ticket_status_module_name = Igniter.Code.Module.module_name("Support.Ticket.Types.Status")
|
||||
domain_module_name = Igniter.Code.Module.module_name(igniter, "Support")
|
||||
ticket_resource = Igniter.Code.Module.module_name(igniter, "Support.Ticket")
|
||||
representative_resource = Igniter.Code.Module.module_name(igniter, "Support.Representative")
|
||||
|
||||
ticket_status_module_name =
|
||||
Igniter.Code.Module.module_name(igniter, "Support.Ticket.Types.Status")
|
||||
|
||||
igniter
|
||||
|> 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},
|
||||
|
||||
# Code Generators
|
||||
{:igniter, "~> 0.3 and >= 0.3.11"},
|
||||
{:igniter, "~> 0.3 and >= 0.3.33"},
|
||||
|
||||
# IO Utilities
|
||||
{: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_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"},
|
||||
"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"},
|
||||
"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"},
|
||||
|
@ -39,7 +39,7 @@
|
|||
"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"},
|
||||
"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"},
|
||||
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
|
||||
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
|
||||
|
|
|
@ -613,7 +613,7 @@ defmodule Ash.Test.Actions.ReadTest do
|
|||
|> strip_metadata()
|
||||
end
|
||||
|
||||
test "a sort will sor rows accordingly when descending", %{
|
||||
test "a sort will sort rows accordingly when descending", %{
|
||||
post1: post1,
|
||||
post2: post2
|
||||
} do
|
||||
|
|
Loading…
Reference in a new issue