#Repeating the same "return" line in one function

6 messages · Page 1 of 1 (latest)

mighty hound
#

Hello,

I'm new to Elixir and Phoenix and found myself repeating code in the same function.

def handle_event("submit_ai_search", %{"card" => params}, socket) do
    send(self(), {:loading, true})

    changeset = %Cards.Card{}
    |> Cards.Card.validate_search_term(params)
    |> Map.put(:action, :insert)

    if changeset.valid? do
      response = AiSearch.search("-", params["search_term"])
      
      case AiSearch.handle_response(response) do
        {:ok, result} ->
          send(self(), {:search_results, result})

          {:noreply, assign(socket, :changeset, changeset)}
        {:error, message} ->
          changeset = changeset
          |> Ecto.Changeset.add_error(:search_term, message)

          send(self(), {:loading, false})
          {:noreply, assign(socket, :changeset, changeset)}
      end
    else
      send(self(), {:loading, false})
      {:noreply, assign(socket, :changeset, changeset)}
    end
  end
end

This line {:noreply, assign(socket, :changeset, changeset)} is repeated 3 times and the send(self(), {:loading, false}) is repeated twice.

Is there a better way to write these blocks of code to avoid code duplication? It would really help if someone could point me in the right direction.

Thanks 🙂

drowsy birch
#
def handle_event("submit_ai_search", %{"card" => params}, socket) do
    changeset = %Cards.Card{}
    |> Cards.Card.validate_search_term(params)
    |> Map.put(:action, :insert)

    with true <- changeset.valid?,
        response = AiSearch.search("-", params["search_term"]),
        {:ok, result} <- AiSearch.handle_response(response) do

      send(self(), {:search_results, result})
      {:noreply, assign(socket, :changeset, changeset)}
    else
      _ ->
        changeset = changeset
        |> Ecto.Changeset.add_error(:search_term, message)

        {:noreply, assign(socket, :changeset, changeset)}
    end
end

I took out your loading messages though, because the process won't be able to react to them until the end of the function anyway. I wonder why you are using send to send the results to yourself instead of assigning them to the socket? (I guess you're sending to the LiveView from a component?)

mighty hound
#

Yea this is a component sending it to the parent liveview.

mighty hound
#

@drowsy birch Thanks for the example. While trying to implement this i'm missing the message variable that is only available when the handle_response function fails.

#

I could change the underscore to a tuple with :error, and :message but then I guess the changeset.valid will never get there?

drowsy birch
#

yeah, then you have to match the separate error cases