I have two live views where the only differences are one function and the template.
defmodule PetLive.Index do
...
def mount(_params, _session, %{assigns: %{current_user: current_user}} = socket) do
{:ok, assign(socket, :pets, list_pets(current_user))}
end
...
defp list_pets(user) do
Pets.list_all_pets(user)
end
end
and
defmodule PetLive.MyPets do
...
def mount(_params, _session, %{assigns: %{current_user: current_user}} = socket) do
{:ok, assign(socket, :pets, list_pets(current_user))}
end
...
defp list_pets(user) do
Pets.list_pets_for_user(user)
end
end
All the rest of the functions are pretty much the same : handleParams/3, four definitions of apply_action/3 and one definition of handleEvent/3. This code is modified from the code generated by mix phx.gen.live.
What is the idiomatic way to de-dupe this code? I’m thinking maybe I want to add a macro so each module just uses the macro and then defines its own list_pets/1 callback. If so, does anyone have any good resources to point me to? Haven’t had to add any macros before.
Or have a single liveview. Depending on how you navigate there, set some kind of mode assign (probably not a good idea if you want to hide all pets from non-admin users, in which case @al2o3cr’s approach would be better).
defp list_pets(socket) do
user = socket.assigns.current_user
mode = socket.assigns.pet_listing_mode
case mode do
:all_pets -> Pets.list_all_pets(user)
:just_current_users_pets -> Pets.list_pets_for_user(user)
end
end
I think this might be the best approach. Then each live view would pass in a function for how that view will list the pets, the markup of how to render the differences for each view, as well as handle any differences that diverge between the two lives views.
Beware trying to make things overly-generic in this situation - if there are that many differences between the pages, what you likely have are two similar LiveViews that both use a common set of UI components.
For instance, I’d recommend you not try to DRY out a short function like:
def mount(_params, _session, %{assigns: %{current_user: current_user}} = socket) do
{:ok, assign(socket, :pets, list_pets(current_user))}
end
My reasoning is that this function’s contents are likely to diverge from other copies as the LiveView grows in complexity.