improvement: support providing an actor

This commit is contained in:
Zach Daniel 2023-08-15 11:06:47 -07:00
parent 39f8358055
commit 7acd7cdeff
4 changed files with 91 additions and 26 deletions

View file

@ -25,7 +25,7 @@ defmodule AshPhoenix.Gen.Live do
{parsed, _, _} =
OptionParser.parse(rest,
strict: [resource_plural: :string]
strict: [resource_plural: :string, actor: :string, no_actor: :boolean]
)
generate(
@ -39,6 +39,34 @@ defmodule AshPhoenix.Gen.Live do
Code.ensure_compiled!(api)
Code.ensure_compiled!(resource)
opts =
if !opts[:actor] && opts[:interactive?] && !opts[:no_actor] do
if Mix.shell().yes?(
"Would you like to name your actor? For example: `current_user`. If you choose no, we will not add any actor logic."
) do
actor =
Mix.shell().prompt("What would you like to name it? For example: `current_user`")
|> String.trim()
if actor == "" do
opts
else
Keyword.put(opts, :actor, actor)
end
else
opts
end
else
opts
end
opts =
if opts[:no_actor] do
Keyword.put(opts, :actor, nil)
else
opts
end
if !Spark.Dsl.is?(api, Ash.Api) do
raise "#{inspect(api)} is not a valid Ash Api module"
end
@ -51,7 +79,9 @@ defmodule AshPhoenix.Gen.Live do
[
api: inspect(api),
resource: inspect(resource),
web_module: inspect(web_module())
web_module: inspect(web_module()),
actor: opts[:actor],
actor_opt: actor_opt(opts)
]
|> add_resource_assigns(api, resource, opts)
@ -122,7 +152,7 @@ defmodule AshPhoenix.Gen.Live do
web_live
|> Path.join(destination)
{formatter_function, options} =
{formatter_function, _options} =
Mix.Tasks.Format.formatter_for_file(destination_path)
contents =
@ -263,19 +293,19 @@ defmodule AshPhoenix.Gen.Live do
nil ->
"""
#{short_name} = #{get_by_pkey}
#{inspect(api)}.destroy!(#{short_name})
#{inspect(api)}.destroy!(#{short_name}#{actor_opt(opts)})
"""
interface ->
"""
#{short_name} = #{get_by_pkey}
#{inspect(resource)}.#{interface.name}!(#{short_name})
#{inspect(resource)}.#{interface.name}!(#{short_name}#{actor_opt(opts)})
"""
end
end
end
defp get_by_pkey(api, resource, pkey, _opts) do
defp get_by_pkey(api, resource, pkey, opts) do
resource
|> Ash.Resource.Info.interfaces()
|> Enum.find(fn interface ->
@ -283,10 +313,18 @@ defmodule AshPhoenix.Gen.Live do
end)
|> case do
nil ->
"#{inspect(api)}.get!(#{inspect(resource)}, #{pkey}: #{pkey})}"
"#{inspect(api)}.get!(#{inspect(resource)}, #{pkey}#{actor_opt(opts)})}"
interface ->
"#{inspect(resource)}.#{interface.name}!(#{pkey})"
"#{inspect(resource)}.#{interface.name}!(#{pkey}#{actor_opt(opts)})"
end
end
defp actor_opt(opts) do
if opts[:actor] do
", actor: socket.assigns.#{opts[:actor]}"
else
""
end
end

View file

@ -44,25 +44,11 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.FormCom
end
@impl true
def update(%{<%= @resource_singular %>: <%= @resource_singular %>} = assigns, socket) do
form =
<%= cond do %>
<% @update_action && @create_action -> %>
if <%= @resource_singular %> do
AshPhoenix.Form.for_update(<%= @resource_singular %>, <%= inspect @update_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %>)
else
AshPhoenix.Form.for_create(<%= @resource %>, <%= inspect @create_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %>)
end
<% @update_action -> %>
AshPhoenix.Form.for_update(<%= @resource_singular %>, <%= inspect @update_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %>)
<% @create_action -> %>
AshPhoenix.Form.for_create(<%= @resource_singular %>, <%= inspect @create_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %>)
<% end %>
def update(assigns, socket) do
{:ok,
socket
|> assign(assigns)
|> assign(form: to_form(form))}
|> assign_form()}
end
@impl true
@ -95,4 +81,22 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.FormCom
end
defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
defp assign_form(%{assigns: %{<%= @resource_singular %>: <%= @resource_singular %>}} = socket) do
form =
<%= cond do %>
<% @update_action && @create_action -> %>
if <%= @resource_singular %> do
AshPhoenix.Form.for_update(<%= @resource_singular %>, <%= inspect @update_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %><%= @actor_opt %>)
else
AshPhoenix.Form.for_create(<%= @resource %>, <%= inspect @create_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %><%= @actor_opt %>)
end
<% @update_action -> %>
AshPhoenix.Form.for_update(<%= @resource_singular %>, <%= inspect @update_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %><%= @actor_opt %>)
<% @create_action -> %>
AshPhoenix.Form.for_create(<%= @resource_singular %>, <%= inspect @create_action.name %>, api: <%= @api %>, as: <%= inspect @resource_singular %><%= @actor_opt %>)
<% end %>
assign(socket, form: to_form(form))
end
end

View file

@ -48,6 +48,9 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Index d
module={<%= inspect Module.concat(@web_module, @resource_alias) %>Live.FormComponent}
id={(@<%= @resource_singular %> && @<%= @resource_singular%>.<%= @pkey %>) || :new}
title={@page_title}
<%= if @actor do %>
<%= @actor %>={@<%= @actor %>}
<% end %>
action={@live_action}
<%= @resource_singular %>={@<%= @resource_singular %>}
patch={~p"<%= @route_prefix %>"}
@ -57,6 +60,9 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Index d
<.modal :if={@live_action == :new} id="<%= @resource_singular %>-modal" show on_cancel={JS.patch(~p"<%= @route_prefix %>")}>
<.live_component
module={<%= inspect Module.concat(@web_module, @resource_alias) %>Live.FormComponent}
<%= if @actor do %>
<%= @actor %>={@<%= @actor %>}
<% end %>
id={:new}
title={@page_title}
action={@live_action}
@ -69,6 +75,9 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Index d
<.live_component
module={<%= inspect Module.concat(@web_module, @resource_alias) %>Live.FormComponent}
id={@<%= @resource_singular %>.<%= @pkey %>}
<%= if @actor do %>
<%= @actor %>={@<%= @actor %>}
<% end %>
title={@page_title}
action={@live_action}
<%= @resource_singular %>={@<%= @resource_singular %>}
@ -83,7 +92,18 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Index d
@impl true
def mount(_params, _session, socket) do
{:ok, stream(socket, :<%= @resource_plural %>, <%= @api %>.read!(<%= @resource %>))}
<%= if @actor do %>
{:ok,
socket
<%= if @actor do %>
|> stream(:<%= @resource_plural %>, <%= @api %>.read!(<%= @resource %>, actor: socket.assigns[:<%= @actor %>]))
<% else %>
|> stream(:<%= @resource_plural %>, <%= @api %>.read!(<%= @resource %>))
<% end %>
|> assign_new(:<%= @actor %>, fn -> nil end)}
<% else %>
{:ok, stream(socket, :<%= @resource_plural %>, <%= @api %>.read!(<%= @resource %>))}
<% end %>
end
@impl true
@ -112,7 +132,7 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Index d
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing <%= @resource_human_plural %>")
<%= if @update_action do %>
<%= if @update_action || @create_action do %>
|> assign(:<%= @resource_singular %>, nil)
<% end %>
end

View file

@ -25,6 +25,9 @@ defmodule <%= inspect Module.concat(@web_module, @resource_alias) %>Live.Show do
id={@<%= @resource_singular %>.id}
title={@page_title}
action={@live_action}
<%= if @actor do %>
<%= @actor %>={@<%= @actor %>}
<% end %>
<%= @resource_singular %>={@<%= @resource_singular %>}
patch={~p"<%= @route_prefix %>/#{@<%= @resource_singular %>}"}
/>