Adding macros to `expr/1`
I'd like to add the
st_*
macros from GeoPostGIS to expr/1
, possibly more in future. These macros do generate exactly the fragment
syntax that is currently supported by expr
, which is pretty nice, but they don't work as-is.
Is doesn't look like it's possible currently to extend Ash.Expr
, and I'm quite interested in changing that, or at least making it possible to mix in external macros in this way using the existing supporting constructs like fragment
.
Has there been any interest/thought up to now on this topic?
https://github.com/bryanjos/geo_postgis/blob/master/lib/geo_postgis.exGitHub
geo_postgis/geo_postgis.ex at master · bryanjos/geo_postgis
Postrex Extension for PostGIS. Contribute to bryanjos/geo_postgis development by creating an account on GitHub.
38 Replies
I'm doing a lot of queries with these things and it would be fantastic to be able to write stuff like
GitHub
Custom predicates & operators · Issue #374 · ash-project/ash
These would be exposed to the expression syntax in code, and can be made available over api extensions as well. I'm thinking something like this: support a custom configured list of functions t...
This is the tracking issue for that feature
in the meantime, there are some things you can do.
1. add calculations to the resources you want to use this with
2. write macros and use them in your exprs. This exact strategy may or may not work but I'm pretty sure we can make something similar to it work at least.
Great that it's on the list
Tried the second example, getting
On the plus side, if we can get that working, then I can make them understand the
arg(_)
-> {:_arg, _}
and friends stuff, so I can write wrappers for these that can be mixed with the usual Ash stuff to some degree.Actually, try this
And if that doesn't work try it without the wrappers
Works:
Not happy:
whats the error?
Same
Need to wrap it in
expr/1
Also if you do it that way it should just "pass through" arg stuff
Then you can st_within(^arg(:foo), :bar)
Aye, that looks right. Will give it a shot when I'm back at my desk.
Some progress:
Nice! So that works?
Yep, got input types working as well 🙂
Nested fragments working, seems good.
Got a bunch of stuff to write with this over the next days for a stress test. If all goes well, I'll find some time next week to roll
ash_geo_postgis
.
One odd thing: cast_input
is not getting called for the argument
type in a create
with set_attribute
, but is getting called when doing a read
with filter expr(...)
.
Call flow for read
/filter expr(...)
goes:
1. :geo_json.cast_input
2. :geometry.cast_stored
Call flow for create
/set_attribute
on the other hand:
1. :geometry.cast_input
2. :geometry.dump_to_native
Because there are multiple input formats that should all be parsed into a geometry and I'd like to let them be specified explicitly, this is not ideal, but I can try to work with the current behaviour, just wanted to check if this is as intended, or is an Ash fix.
(ideal would be that cast_input
for the input type always gets called for an argument
)🤔 if you could make a test showing an example of not calling
cast_input
when providing input for pretty much any argument anywhere, then it is almost certainly a bug 🙂
There are some cases where we don't call apply_constraints/2
(specifically when building queries)In this case,
cast_input
is getting called, but only on the underlying type (:geometry
), not the input type (:geo_json
), which seems wrong to me.So do you have
:geo_json
set up as a type alias somewhere I assume?
like w/ the custom short names config?Correct
gotcha. In that case that sounds like a bug 🙂
Yeah
changeset.ex
has the cast to underlying in force_change_attribute
but didn't see the input cast anywhere there or in the set_sttribute
built-in.well the
set_attribute
builtin calls force_change_attribute
under the hood
the problem is in the action argument casting I imagineYeah I know, but it's only casting to the underlying type, not from the input type
Yeah, that makes sense
arguments get casted up-front
Right, so that's what I was thinking, maybe this is supposed to be happening further up the request chain. Where is it supposed to be getting casted?
it happens in
set_argument/3
its interesting...I think I might see the problem
maybe.
Can I see how you're calling the action?okay yeah nvm them
um....how sure are you that its not calling the function you want it to call?
create one is bare
just want to check our bases
are you like inspecting something in the
cast_input
function of your types?Reasonably sure... I have
dbg
breaks on all my cast_inputs
for the type wrappers.and you definitely have your short names configured properly?
Same short names and same breaks are being used to validate the flow for the read action where it's working.
I don't have a break on the
:error
catch-all but if it's getting an error out of cast and passing it through anyways, that's a bug as well.true, but lets check it just to be sure 😄
Back at desk in 5
Also try out just this
Resource |> Ash.Changeset.for_action(:create, %{...input})
it should cast the arguments there w/o even calling the actionYep,
Thing |> Ash.Changeset.for_action(:create, %{area: %{}})
triggers :geojson.cast_input
correctly.
And... So does the code interface call now.🤔
:thinkies:
When using
ash_geo
library, I get
the docs for ash_geo
and ash
are sparse around expr
.
@\ ឵឵឵Fixes to outdated example in the readme and updates to test suite for latest
ash
and ash_postgres
are up now on Hex ash_geo v0.1.3
.