Matt Beanland
Matt Beanland
AEAsh Elixir
Created by Matt Beanland on 5/24/2025 in #support
How to create a negative test for a verifier
Hi, I'm working on adding some verifiers to the transformer for the Ash Neo4j DataLayer, and I've got a simple Verifier that checks neo4j convention on the resource label Here is the verifier:
defmodule AshNeo4j.Verifiers.VerifyLabelCamelCase do
@moduledoc "Verifies that the label is camelcase"
use Spark.Dsl.Verifier

alias Spark.Dsl.Verifier
alias Spark.Error.DslError
@regex ~r/^[A-Z][a-zA-Z]*$/

@impl true
def verify(dsl) do
IO.inspect(dsl, label: :verify_label_camel_case_dsl)
resource = Verifier.get_persisted(dsl, :module) |> IO.inspect(label: :resource)
neo4j = Map.get(dsl, [:neo4j])
label = Keyword.get(neo4j.opts, :label, nil) |> IO.inspect(label: :label)

cond do
label == nil ->
{:error,
DslError.exception(
module: resource,
message: "Label missing"
)}

Regex.match?(@regex, Atom.to_string(label)) ->
:ok

true ->
{:error,
DslError.exception(
module: resource,
message: "Label must be CamelCase"
)}
end
end
end
defmodule AshNeo4j.Verifiers.VerifyLabelCamelCase do
@moduledoc "Verifies that the label is camelcase"
use Spark.Dsl.Verifier

alias Spark.Dsl.Verifier
alias Spark.Error.DslError
@regex ~r/^[A-Z][a-zA-Z]*$/

@impl true
def verify(dsl) do
IO.inspect(dsl, label: :verify_label_camel_case_dsl)
resource = Verifier.get_persisted(dsl, :module) |> IO.inspect(label: :resource)
neo4j = Map.get(dsl, [:neo4j])
label = Keyword.get(neo4j.opts, :label, nil) |> IO.inspect(label: :label)

cond do
label == nil ->
{:error,
DslError.exception(
module: resource,
message: "Label missing"
)}

Regex.match?(@regex, Atom.to_string(label)) ->
:ok

true ->
{:error,
DslError.exception(
module: resource,
message: "Label must be CamelCase"
)}
end
end
end
Here is an invalid resource, the neo4j (node) label for the InvalidLabel resource should be :Comment not :comment
defmodule InvalidLabel do
@moduledoc false
use Ash.Resource,
domain: AshNeo4j.Test.Domain,
data_layer: AshNeo4j.DataLayer

neo4j do
label :comment
store [:title]
translate id: :uuid
end

attributes do
uuid_primary_key :id
attribute :title, :string, public?: true
end
end
defmodule InvalidLabel do
@moduledoc false
use Ash.Resource,
domain: AshNeo4j.Test.Domain,
data_layer: AshNeo4j.DataLayer

neo4j do
label :comment
store [:title]
translate id: :uuid
end

attributes do
uuid_primary_key :id
attribute :title, :string, public?: true
end
end
I'm at a loss how to write a negative test, as the module simply doesn't compile. Ideally I'd like to delay compilation until in the unit test, and pass the test if it errors. Help appreciated.
5 replies
AEAsh Elixir
Created by Matt Beanland on 5/21/2025 in #today-i-learned
_ in Integer, Float
iex> 1_000
1000
iex> 1_000.0
1000.0
iex> 1_000
1000
iex> 1_000.0
1000.0
1 replies
AEAsh Elixir
Created by Matt Beanland on 5/21/2025 in #today-i-learned
Comparing Durations....
Wasn't today but have been working on adding :duration, Ash.Type.Duration to Ash as want it for my AshNeo4j datalayer, etc., and learned that while Durations can be added and subtracted, they aren't so easy to compare, particularly when larger inability to compare weeks and months without a reference instant. So we don't have a comparator on Durations, although durations small enough to convert to timeout (with Kernel to_timeout) can be. That said durations are really useful in expressions, in Ash we've added support so they can be added/subtracted from temporal types DateTime|Date|Time|NaiveDateTime which uses the respective shift, (subtract also uses Duration.negate()), with the result the same temporal type. Durations can be added and subtracted with result in duration. Durations can also be negated.
1 replies
AEAsh Elixir
Created by Matt Beanland on 5/9/2025 in #support
Changeset truncates Time, DateTime and NaiveDateTime to whole seconds
Ash 3.5.8 is removing microseconds from Time, DateTime and NaiveDateTime, which I think is a bug. I've noticed this in a create changeset. For example ~U[2025-05-09 08:02:21.294214Z] is truncated to ~U[2025-05-09 08:02:21Z].
42 replies