AE
Ash Elixir•3y ago
fekle

Ash Relationships with existing Ecto Repos

Hi there, I'm currently working on integrating Ash into my existing Phoenix/Ecto/Postgres app. So far Ash looks amazing and seems to be exactly what I'm looking for - the power and balance of ecto but without having to create basic utility functions over and over and over again 😉 Sorry if my question has already been answered, I couldn't find anything on GH, google, docs or Discord. However I don't yet want to migrate all my existing Ecto (Phoenix Context) resources all at once, but go step by step. Now, I added a new Repo, Registry and API with a new resource and that works fine. However now I want to add a :belongs_to in my new resource's :relationships - and that needs to be a user, so the resource belongs to a user. Thing is, the User resource already exists as a normal Ecto schema that is used in my app, so ash tells me it can't find the resource. Is there some way to have a "compatibility" layer between an existing ecto schema and an ash resource? Thanks!
16 Replies
ZachDaniel
ZachDaniel•3y ago
Unfortunately there is nothing that lets you directly relate ecto schemas and ash resources at this time
fekle
fekleOP•3y ago
I understand, thanks for your swift reply! So i'll just use a normal uuid field for now and manage the relationship manually, and when I migrate my user resource i should be able to reuse the existing uuid field.
ZachDaniel
ZachDaniel•3y ago
There also isn't really a downside to having a duplicate ash resource for your ecto schema
fekle
fekleOP•3y ago
so that means i could have a new ash resource for my users which uses the same postgres table as my existing ecto schema, and keep using my ecto schema for existing functions? sounds like a good compromise
ZachDaniel
ZachDaniel•3y ago
Yep! Others have done pretty much exactly that.
fekle
fekleOP•3y ago
thanks a lot! I will do that 🙂 One more quick question that I couldnt find the answer for: When using AshPhoenix.Form, is it possible to add values that are always applied when validating or submitting the form? For example a user id? I know that i can do this with a hidden input or by modifying the params before validating/submitting, but is there a more idiomatic way? The "params" option gets lost after the first validate.
ZachDaniel
ZachDaniel•3y ago
You can use the prepare_source option
Form.for_create(..., prepare_source: fn changeset ->
Ash.Changeset.set_argument(....)
end)
Form.for_create(..., prepare_source: fn changeset ->
Ash.Changeset.set_argument(....)
end)
Actually I think in your case you want before_submit which is an option you add to the form submission
fekle
fekleOP•3y ago
Ah, i saw that before but that didnt work, as i want to set an attribute and not an argument. But using Ash.Changeset.change_attribute/3 in this works.
ZachDaniel
ZachDaniel•3y ago
Form.submit(..., before_submit: fn changeset ->
...
end)
Form.submit(..., before_submit: fn changeset ->
...
end)
I'd suggest doing it with before_submit to avoid malicious things like the user including the field and your value getting overwritten prepare_source -> put users params into action -> before_submit
fekle
fekleOP•3y ago
I understand, yeah thats the reason I dont like using hidden fields etc. before_submit unfortunately only works with submit and not validate, i need the attribute for validation
ZachDaniel
ZachDaniel•3y ago
🤔 interesting...maybe use both? I think there are definitely some ergonomics to be improved there.
fekle
fekleOP•3y ago
yes some kind of "unmodifyable values" that are always overwritten in the params. Maybe I'll have a look at opening a PR for that 🙂
ZachDaniel
ZachDaniel•3y ago
So you need the attribute for validation because otherwise the form says its invalid, right? because you can technically submit an invalid form with force?: true on the submit so you could just let the form be invalid until then?
fekle
fekleOP•3y ago
yes, its a bit of an edge case. the item in the form belongs to a user, and has a number field - but the max value of the number field depends on a value in the user profile, so i need it for validation
ZachDaniel
ZachDaniel•3y ago
interesting. Then yeah I think you might be right. If the form accepts some values on form creation/validation like immutable_values: ... that would solve for it.
fekle
fekleOP•3y ago
In the meanwhile i'm thinking that maybe using an argument and handling the value in my actions is the better way do do this. there i could use the argument user_id for my validation and then always setting the attribute based on that argument thank you very much for your help, that cleared up things for me! 🙂

Did you find this page helpful?