Jmanda
Jmanda
AEAsh Elixir
Created by Jmanda on 4/20/2024 in #showcase
My proof of concept project (FleetMS) built with Ash
Yes, am rewriting everything here: https://github.com/jmnda-dev/fleetms, nothing much yet but will push much over the weekend
6 replies
AEAsh Elixir
Created by Jmanda on 4/20/2024 in #showcase
My proof of concept project (FleetMS) built with Ash
Sure 😁
6 replies
AEAsh Elixir
Created by drumusician on 6/11/2023 in #support
Custom / virtual fields on read
You can also try to add primary? true to your read action? And it's likely you're referencing a module that does not exist, take a look at these discussions: https://discord.com/channels/711271361523351632/799097774523547669/861263803056652288 and https://discord.com/channels/711271361523351632/799097774523547669/823438146804252702
17 replies
AEAsh Elixir
Created by drumusician on 6/11/2023 in #support
Custom / virtual fields on read
So I have never used AshGraphql before, but perhaps you can share your code I see how you are defining the GraphQL api in your resource? At least that will provide more context.
17 replies
AEAsh Elixir
Created by drumusician on 6/11/2023 in #support
Custom / virtual fields on read
Awesome 🥳
17 replies
AEAsh Elixir
Created by drumusician on 6/11/2023 in #support
Custom / virtual fields on read
Do you want to have a virtual field in your resource whose value is based on the existing field/attribute? If that's the case the you can use Ash Calculations: https://ash-hq.org/docs/guides/ash/latest/topics/calculations. For example if you have a User resource like the following:
defmodule MyApp.Accounts.User do
...
attributes do
attribute :first_name, :string
attribute :last_name, :string
end
...
end
defmodule MyApp.Accounts.User do
...
attributes do
attribute :first_name, :string
attribute :last_name, :string
end
...
end
you can add a full_name calculation(virtual field) to your resource by declaring a calculation :
calculations do
calculate :full_name, :string, expr(first_name <> " " <> last_name)
end
calculations do
calculate :full_name, :string, expr(first_name <> " " <> last_name)
end
that way you can now use user.full_name even if its not defined in your resource attributes. I think you can use the calculation in Ash.Query as well. If that's not what you're looking for you can share some code to provide additional context.
17 replies
AEAsh Elixir
Created by Jmanda on 4/30/2023 in #support
Implementating auto-incrementing/sequence fields in Ash Resources
Thanks for your feedback. I will also do some research regarding database triggers. For the sake of making progress 😄, will try to implement what I mentioned previously then do proper implementation later.
3 replies
AEAsh Elixir
Created by Jmanda on 3/19/2023 in #support
** (KeyError) key :options not found: Error on AshPhoenix.Form submit
No worries I understand 😁 , thanks for your feedback
9 replies
AEAsh Elixir
Created by Jmanda on 3/19/2023 in #support
** (KeyError) key :options not found: Error on AshPhoenix.Form submit
Oh I see
9 replies
AEAsh Elixir
Created by Jmanda on 3/19/2023 in #support
** (KeyError) key :options not found: Error on AshPhoenix.Form submit
Here is the stacktrace:
[error] GenServer #PID<0.1234.0> terminatingvehicle
** (KeyError) key :options not found in:

#AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"name" => ""}, source: #Ash.Changeset<action_type: :create, action: :create, attributes: %{title: nil} ...
valid?: false, errors: true, submitted_once?: true, just_submitted?: true, ...>

(ash_phoenix 1.2.10) lib/ash_phoenix/form/form.ex:1438: AshPhoenix.Form.submit/2
(todo 0.1.0) lib/todo_web/live/todo_live/form_component.ex:87: MyAppWeb.TodoLive.FormComponent.save_todo/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) my_app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F03OyPkC1xNe-wWF", event: "event", payload: %{"cid" => 3, "event" => "save", "type" => "form", "value" => "todo%5Bname%5D="}, ref: "8", join_ref: "4"}
[error] GenServer #PID<0.1234.0> terminatingvehicle
** (KeyError) key :options not found in:

#AshPhoenix.Form<resource: MyApp.Todos.Todo, action: :create, type: :create, params: %{"name" => ""}, source: #Ash.Changeset<action_type: :create, action: :create, attributes: %{title: nil} ...
valid?: false, errors: true, submitted_once?: true, just_submitted?: true, ...>

(ash_phoenix 1.2.10) lib/ash_phoenix/form/form.ex:1438: AshPhoenix.Form.submit/2
(todo 0.1.0) lib/todo_web/live/todo_live/form_component.ex:87: MyAppWeb.TodoLive.FormComponent.save_todo/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) my_app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F03OyPkC1xNe-wWF", event: "event", payload: %{"cid" => 3, "event" => "save", "type" => "form", "value" => "todo%5Bname%5D="}, ref: "8", join_ref: "4"}
This is the code in handle event and on line 87 in my FormComponent:
def handle_event("save", %{"todo" => todo_params}, socket) do
save_todo(socket, socket.assigns.action, todo_params)
end
def handle_event("save", %{"todo" => todo_params}, socket) do
save_todo(socket, socket.assigns.action, todo_params)
end
defp save_todo(socket, :new, todo_params) do
IO.inspect(socket.assigns.form, label: "FORM")
case AshPhoenix.Form.submit(socket.assigns.form, params: todo_params) do
{:ok, todo} ->
notify_parent({:saved, todo})
......
end
defp save_todo(socket, :new, todo_params) do
IO.inspect(socket.assigns.form, label: "FORM")
case AshPhoenix.Form.submit(socket.assigns.form, params: todo_params) do
{:ok, todo} ->
notify_parent({:saved, todo})
......
end
9 replies
AEAsh Elixir
Created by Jmanda on 2/17/2023 in #support
Override/Extend AshAuthentication Sign in
Okay will do that. Thanks for the help once again 😃
10 replies
AEAsh Elixir
Created by Jmanda on 2/17/2023 in #support
Override/Extend AshAuthentication Sign in
@Zach Daniel I managed to implement that and it worked. However I have an issue, the current user is missing in the liveview socket I have set the on_mount: callback like this:
defmodule MyAppWeb.LiveUserAuth do
def on_mount(:live_user_required, _params, %{"tenant" => tenant} = _session, socket) do
Ash.set_tenant(tenant)
IO.inspect(socket, label: "socket")

if socket.assigns[:current_user] do
{:cont, socket}
else
{:halt, Phoenix.LiveView.redirect(socket, to: "/sign-in")}
end
end
end
defmodule MyAppWeb.LiveUserAuth do
def on_mount(:live_user_required, _params, %{"tenant" => tenant} = _session, socket) do
Ash.set_tenant(tenant)
IO.inspect(socket, label: "socket")

if socket.assigns[:current_user] do
{:cont, socket}
else
{:halt, Phoenix.LiveView.redirect(socket, to: "/sign-in")}
end
end
end
And in the router.ex
scope "/", MyAppWeb do
pipe_through :browser

ash_authentication_live_session :ash_authentication,
on_mount: {MyAppWeb.LiveUserAuth, :live_user_required} do
live "/", DashboardLive.Index, :index
...
end
end
scope "/", MyAppWeb do
pipe_through :browser

ash_authentication_live_session :ash_authentication,
on_mount: {MyAppWeb.LiveUserAuth, :live_user_required} do
live "/", DashboardLive.Index, :index
...
end
end
* note that am setting the tenant, as the user is not on the public schema So whats happening is that when the liveview mounts(first time when socket not connected), the socket has a current_user, cause the tenant is the Process, however when the liveview is mounted again(when socket is connected), the socket does not have a current_user assigned, probably because the liveview is now in a new PID, where tenant is not set, resulting the user query running on the public_schema instead of a tenant schema. Is there a way I can resolve this?
10 replies
AEAsh Elixir
Created by Jmanda on 2/17/2023 in #support
Override/Extend AshAuthentication Sign in
Thank you Zach, I will try that
10 replies
AEAsh Elixir
Created by waseigo on 2/10/2023 in #support
Example of setting a has_one relationship
You can take a look at https://ash-hq.org/docs/module/ash/latest/ash-query#function-load-2 for loading nested relationships
10 replies
AEAsh Elixir
Created by waseigo on 2/10/2023 in #support
Example of setting a has_one relationship
I think in App.Api.Variant you have to define a belongs_to as supposed to adding attribute :item_id, :uuid, so something like:
relationships do
belongs_to :item, App.Api.Item
end
relationships do
belongs_to :item, App.Api.Item
end
10 replies
AEAsh Elixir
Created by Jmanda on 2/8/2023 in #support
Create an Org on public schema and initial User on Org schema
Updated the deps, am now able to create a User using :register_with_password action
22 replies
AEAsh Elixir
Created by Jmanda on 2/8/2023 in #support
Create an Org on public schema and initial User on Org schema
Alright 😁 , let me do that, will report back
22 replies
AEAsh Elixir
Created by Jmanda on 2/8/2023 in #support
Create an Org on public schema and initial User on Org schema
** (UndefinedFunctionError) function Ash.NotLoaded.__changeset__/0 is undefined or private
(ash 2.5.10) Ash.NotLoaded.__changeset__()
(ecto 3.9.4) lib/ecto/changeset.ex:409: Ecto.Changeset.change/2
(ecto 3.9.4) lib/ecto/changeset/relation.ex:173: Ecto.Changeset.Relation.do_change/4
(ecto 3.9.4) lib/ecto/changeset/relation.ex:335: Ecto.Changeset.Relation.single_change/5
(ecto 3.9.4) lib/ecto/changeset/relation.ex:165: Ecto.Changeset.Relation.change/3
...
** (UndefinedFunctionError) function Ash.NotLoaded.__changeset__/0 is undefined or private
(ash 2.5.10) Ash.NotLoaded.__changeset__()
(ecto 3.9.4) lib/ecto/changeset.ex:409: Ecto.Changeset.change/2
(ecto 3.9.4) lib/ecto/changeset/relation.ex:173: Ecto.Changeset.Relation.do_change/4
(ecto 3.9.4) lib/ecto/changeset/relation.ex:335: Ecto.Changeset.Relation.single_change/5
(ecto 3.9.4) lib/ecto/changeset/relation.ex:165: Ecto.Changeset.Relation.change/3
...
22 replies
AEAsh Elixir
Created by Jmanda on 2/8/2023 in #support
Create an Org on public schema and initial User on Org schema
So what can an implementation in register_your_user_here(..., tenant: org.schema_name) look like? Is it right to do it this way:
attrs = %{email: "[email protected]", password: "password12345", password_confirmation: "password12345"}

User
|> Ash.Changeset.for_create(:register_with_password, attrs)
|> Accounts.create()
attrs = %{email: "[email protected]", password: "password12345", password_confirmation: "password12345"}

User
|> Ash.Changeset.for_create(:register_with_password, attrs)
|> Accounts.create()
although the above code is raising an error:
22 replies
AEAsh Elixir
Created by Jmanda on 1/31/2023 in #support
Setting Tenant when using Context Multitenancy
In the meantime will just "handroll" my own, shouldn't be hard I have done it before 😁
23 replies