From 7c42dd8a3a58e44bb12d3ceeb6283d19032bc5fa Mon Sep 17 00:00:00 2001 From: shibao Date: Sat, 3 Jun 2023 19:53:44 -0400 Subject: [PATCH] improve Containers.list_tags --- lib/cannery/containers.ex | 55 +++++++++++++++----------- lib/cannery_web/live/tag_live/index.ex | 2 +- test/cannery/containers_test.exs | 8 ++-- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/lib/cannery/containers.ex b/lib/cannery/containers.ex index e4bd0c9..4bf0ded 100644 --- a/lib/cannery/containers.ex +++ b/lib/cannery/containers.ex @@ -7,7 +7,7 @@ defmodule Cannery.Containers do import Ecto.Query, warn: false alias Cannery.{Accounts.User, Ammo.Pack, Repo} alias Cannery.Containers.{Container, ContainerTag, Tag} - alias Ecto.Changeset + alias Ecto.{Changeset, Queryable} @container_preloads [:tags] @@ -289,6 +289,9 @@ defmodule Cannery.Containers do # Container Tags + @type list_tags_option :: {:search, String.t() | nil} + @type list_tags_options :: [list_tags_option()] + @doc """ Returns the list of tags. @@ -297,38 +300,42 @@ defmodule Cannery.Containers do iex> list_tags(%User{id: 123}) [%Tag{}, ...] - iex> list_tags("cool", %User{id: 123}) + iex> list_tags(%User{id: 123}, search: "cool") [%Tag{name: "my cool tag"}, ...] """ @spec list_tags(User.t()) :: [Tag.t()] - @spec list_tags(search :: nil | String.t(), User.t()) :: [Tag.t()] - def list_tags(search \\ nil, user) + @spec list_tags(User.t(), list_tags_options()) :: [Tag.t()] + def list_tags(%User{id: user_id}, opts \\ []) do + from(t in Tag, as: :t, where: t.user_id == ^user_id) + |> list_tags_search(Keyword.get(opts, :search)) + |> Repo.all() + end - def list_tags(search, %User{id: user_id}) when search |> is_nil() or search == "", - do: Repo.all(from t in Tag, where: t.user_id == ^user_id, order_by: t.name) + @spec list_tags_search(Queryable.t(), search :: String.t() | nil) :: Queryable.t() + defp list_tags_search(query, search) when search in ["", nil], + do: query |> order_by([t: t], t.name) - def list_tags(search, %User{id: user_id}) when search |> is_binary() do + defp list_tags_search(query, search) when search |> is_binary() do trimmed_search = String.trim(search) - Repo.all( - from t in Tag, - where: t.user_id == ^user_id, - where: - fragment( - "? @@ websearch_to_tsquery('english', ?)", - t.search, - ^trimmed_search - ), - order_by: { - :desc, - fragment( - "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", - t.search, - ^trimmed_search - ) - } + query + |> where( + [t: t], + fragment( + "? @@ websearch_to_tsquery('english', ?)", + t.search, + ^trimmed_search + ) ) + |> order_by([t: t], { + :desc, + fragment( + "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", + t.search, + ^trimmed_search + ) + }) end @doc """ diff --git a/lib/cannery_web/live/tag_live/index.ex b/lib/cannery_web/live/tag_live/index.ex index 84ef3fa..c93439c 100644 --- a/lib/cannery_web/live/tag_live/index.ex +++ b/lib/cannery_web/live/tag_live/index.ex @@ -75,6 +75,6 @@ defmodule CanneryWeb.TagLive.Index do end defp display_tags(%{assigns: %{search: search, current_user: current_user}} = socket) do - socket |> assign(tags: Containers.list_tags(search, current_user)) + socket |> assign(tags: Containers.list_tags(current_user, search: search)) end end diff --git a/test/cannery/containers_test.exs b/test/cannery/containers_test.exs index e5f7492..a80ecbb 100644 --- a/test/cannery/containers_test.exs +++ b/test/cannery/containers_test.exs @@ -168,10 +168,10 @@ defmodule Cannery.ContainersTest do tag_fixture(%{name: "bullet", desc: "pews brass shell"}, user_fixture()) # name - assert Containers.list_tags("bullet", current_user) == [tag_a] - assert Containers.list_tags("bullets", current_user) == [tag_a] - assert Containers.list_tags("hollow", current_user) == [tag_b] - assert Containers.list_tags("hollows", current_user) == [tag_b] + assert Containers.list_tags(current_user, search: "bullet") == [tag_a] + assert Containers.list_tags(current_user, search: "bullets") == [tag_a] + assert Containers.list_tags(current_user, search: "hollow") == [tag_b] + assert Containers.list_tags(current_user, search: "hollows") == [tag_b] end test "get_tag!/2 returns the tag with given id", %{tag: tag, current_user: current_user} do