gordoneliel
gordoneliel
AEAsh Elixir
Created by gordoneliel on 9/22/2023 in #support
Preload relationship during action
I know we can use load to load an association during an action. However this only loads the relationship after the action is completed. I would like to do something like this:
action :update do
change set_attribute(:starts_at, DateTime.utc_now(), new?: true)
change load([:my_resource])
change SomeChangeThatUsesResource
end
action :update do
change set_attribute(:starts_at, DateTime.utc_now(), new?: true)
change load([:my_resource])
change SomeChangeThatUsesResource
end
Using :my_resource in the next change doesn't preload the relationship at the moment to I get a #Ash.NotLoaded<:relationship> . Im sure this is possible? Wasn't able to figure it out from the docs so wondering if anyone has a similar situation
48 replies
AEAsh Elixir
Created by gordoneliel on 9/14/2023 in #support
How To: Return a computed relationship in a read.
I have a resource like Posts. Each Post has a 'top comment'. So when i'm fetching a Post or list of Posts, I will like it to include the top comment like so: post.top_comment. I'm currently trying to use a preparation to load this relationship but not sure how to execute it on the Ash.Query side of things. Any ideas here would be appreciated!
25 replies
AEAsh Elixir
Created by gordoneliel on 9/12/2023 in #support
How to: DateTime validation with compare/2
Im trying to compare datetime in an action with compare/2. Code looks like this:
validate compare(:resumes_at, greater_than: DateTime.utc_now(:microsecond)),
message: "resumes_at must be in the future",
where: [present(:resumes_at)]
validate compare(:resumes_at, greater_than: DateTime.utc_now(:microsecond)),
message: "resumes_at must be in the future",
where: [present(:resumes_at)]
Weird thing is this validation fails even when resumes_at is in the future. Does this work or are there other ways of easily comparing datetimes in inline changes?
12 replies
AEAsh Elixir
Created by gordoneliel on 9/8/2023 in #support
How To: Atomic update with a where clause
I'm trying to implement this workflow: Update a timestamp atomically on an existing record if the new timestamp is greater than the old one, and the old one hasn't changed while im updating it(optimistic update). I know atomics just dropped on Ash core so wondering if this could be achieved with it. This is the ash action in question:
update :mark_as_paid do
argument :invoice_event_ts, :utc_datetime_usec, allow_nil?: false

change set_attribute(:invoice_status, :paid)
change atomic_update(:last_invoice_event_ts, arg(:invoice_event_ts))
end
update :mark_as_paid do
argument :invoice_event_ts, :utc_datetime_usec, allow_nil?: false

change set_attribute(:invoice_status, :paid)
change atomic_update(:last_invoice_event_ts, arg(:invoice_event_ts))
end
9 replies
AEAsh Elixir
Created by gordoneliel on 9/7/2023 in #support
How To: Exclusion constraints in AshPostgres
Im setting up an exclusion constraint an a few time attributes. I dont see anywhere in the docs an affordance for exclusion constraints, only check constraints, so what I did is create the migration for the exclusion manually, but now im getting an ecto error asking me to add it to the changeset.
If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `exclusion_constraint/3` on your changeset with the constraint
`:name` as an option.
If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `exclusion_constraint/3` on your changeset with the constraint
`:name` as an option.
Question is, is this supported? Is there a way to add the exclusion without having to do it manually for each changeset in each action?
3 replies
AEAsh Elixir
Created by gordoneliel on 8/21/2023 in #support
Filtering by enum attribute
I have an Ash resource that has an enum field status. Im using AshJsonApi to pass in a filter: filter[status]=active,incomplete. This doesnt seem to work out of the box so I implemented a preperation where I do this:
defp filter_by_status(query) do
case Ash.Changeset.get_argument(query, :filter) do
%{"status" => statuses} ->
all_statuses = String.split(statuses, ",")
Ash.Query.filter(query, status in ^all_statuses)

_ ->
query
end
end
defp filter_by_status(query) do
case Ash.Changeset.get_argument(query, :filter) do
%{"status" => statuses} ->
all_statuses = String.split(statuses, ",")
Ash.Query.filter(query, status in ^all_statuses)

_ ->
query
end
end
This does not work however, returns the following error:
[error] FrameworkError: Framework Error | something went wrong. Error messaging is incomplete so far: %Ash.Error.Query.InvalidFilterValue{message: nil, value: "active,incomplete", context: #Ecto.Query<from m0 in MembershipService.Memberships.Membership, as: 0, where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) ==
type(
^"active,incomplete",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
), where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) in [
type(
^"active",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
),
type(
^"incomplete",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
)
],
[error] FrameworkError: Framework Error | something went wrong. Error messaging is incomplete so far: %Ash.Error.Query.InvalidFilterValue{message: nil, value: "active,incomplete", context: #Ecto.Query<from m0 in MembershipService.Memberships.Membership, as: 0, where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) ==
type(
^"active,incomplete",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
), where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) in [
type(
^"active",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
),
type(
^"incomplete",
{:parameterized, Ash.Type.Atom.EctoType,
one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
)
],
Is there an example or an way to filter by an enum?
12 replies
AEAsh Elixir
Created by gordoneliel on 8/11/2023 in #support
How to: Keyset pagination in AshJsonApi
When I enable keyset pagination in my read action, I get an error
** (KeyError) key :metadata not found in: #SomeAshResource..
** (KeyError) key :metadata not found in: #SomeAshResource..
Using offset pagination works, but doesnt show me the pagination metadata in the response either, just first/last page links This is my read action:
read :read do
primary? true
pagination keyset?: true, default_limit: 15, countable: true, max_page_size: 100
end
read :read do
primary? true
pagination keyset?: true, default_limit: 15, countable: true, max_page_size: 100
end
Are there any examples of Keyset pagination with ash?
7 replies
AEAsh Elixir
Created by gordoneliel on 8/4/2023 in #support
Testing: How to approach testing
Im trying to write some tests for my ash resources, and want to test errors in particular, is there a recommended way of going about this? The testing docs are a bit anemic, wonder if folks have some strategies here. In particular when matching on ash errors, I have to match on large error structs with the stacktrace. Is there a simplier way of going about this?
10 replies
AEAsh Elixir
Created by gordoneliel on 8/3/2023 in #support
How to: Conditional validation with built-ins
Im trying to validate an embedded field "payment_method" when a certain param/attribute has a specific value. I've tried to do this:
accept [:collection_method, :billing_cycle_anchor, :customer, :payment_method]
validate present([:collection_method, :customer])
validate present(:payment_method),
where: [argument_equals(:collection_method, :charge_automatically)],
message: "payment_method is required when collection method is charge_automatically"
accept [:collection_method, :billing_cycle_anchor, :customer, :payment_method]
validate present([:collection_method, :customer])
validate present(:payment_method),
where: [argument_equals(:collection_method, :charge_automatically)],
message: "payment_method is required when collection method is charge_automatically"
But when I omit the "payment_method" param when sending a request to create, I get a "Invalid value provided for payment_method: is invalid." I've tried argument_equals, attribute_equals and none seem to work
19 replies
AEAsh Elixir
Created by gordoneliel on 7/31/2023 in #support
Creating index from identity or custom index creates bad migration
When generating a migration from either an identity or custom index, I'm getting a weird migration: Datalayer:
postgres do
table "plans"
repo MyApp.Repo
migration_defaults features: "[]"

custom_indexes do
index [:id, :organization_id],
name: "unique_org_plan",
unique: true,
message: "a plan can only be tied to one organization"
end
end
postgres do
table "plans"
repo MyApp.Repo
migration_defaults features: "[]"

custom_indexes do
index [:id, :organization_id],
name: "unique_org_plan",
unique: true,
message: "a plan can only be tied to one organization"
end
end
Migration generated:
create index(:plans, ["organization_id", "id", "organization_id"],
name: "unique_org_plan",
unique: true
)
create index(:plans, ["organization_id", "id", "organization_id"],
name: "unique_org_plan",
unique: true
)
Doing this because the relationship migration generated by a belongs_to creating a transitive unique fk index on the multi-tenant attribute "organization_id"
6 replies
AEAsh Elixir
Created by gordoneliel on 7/29/2023 in #support
AshJsonAPI Responses
When updating a resource backed by jsonapi, responses return a 201 instead of 200, is this a bug or am I doing something wrong?
10 replies
AEAsh Elixir
Created by gordoneliel on 7/17/2023 in #support
AshJsonApi + Managed Relationships
Are there any examples of AshJsonApi, the docs seem outdated. Im trying to get managed relationships to work through a 'parent' resource.
34 replies