improve Containers.list_tags

This commit is contained in:
shibao 2023-06-03 19:53:44 -04:00
parent 79c97d7502
commit 7c42dd8a3a
3 changed files with 36 additions and 29 deletions

View File

@ -7,7 +7,7 @@ defmodule Cannery.Containers do
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Cannery.{Accounts.User, Ammo.Pack, Repo} alias Cannery.{Accounts.User, Ammo.Pack, Repo}
alias Cannery.Containers.{Container, ContainerTag, Tag} alias Cannery.Containers.{Container, ContainerTag, Tag}
alias Ecto.Changeset alias Ecto.{Changeset, Queryable}
@container_preloads [:tags] @container_preloads [:tags]
@ -289,6 +289,9 @@ defmodule Cannery.Containers do
# Container Tags # Container Tags
@type list_tags_option :: {:search, String.t() | nil}
@type list_tags_options :: [list_tags_option()]
@doc """ @doc """
Returns the list of tags. Returns the list of tags.
@ -297,38 +300,42 @@ defmodule Cannery.Containers do
iex> list_tags(%User{id: 123}) iex> list_tags(%User{id: 123})
[%Tag{}, ...] [%Tag{}, ...]
iex> list_tags("cool", %User{id: 123}) iex> list_tags(%User{id: 123}, search: "cool")
[%Tag{name: "my cool tag"}, ...] [%Tag{name: "my cool tag"}, ...]
""" """
@spec list_tags(User.t()) :: [Tag.t()] @spec list_tags(User.t()) :: [Tag.t()]
@spec list_tags(search :: nil | String.t(), User.t()) :: [Tag.t()] @spec list_tags(User.t(), list_tags_options()) :: [Tag.t()]
def list_tags(search \\ nil, user) 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 == "", @spec list_tags_search(Queryable.t(), search :: String.t() | nil) :: Queryable.t()
do: Repo.all(from t in Tag, where: t.user_id == ^user_id, order_by: t.name) 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) trimmed_search = String.trim(search)
Repo.all( query
from t in Tag, |> where(
where: t.user_id == ^user_id, [t: t],
where:
fragment( fragment(
"? @@ websearch_to_tsquery('english', ?)", "? @@ websearch_to_tsquery('english', ?)",
t.search, t.search,
^trimmed_search ^trimmed_search
), )
order_by: { )
|> order_by([t: t], {
:desc, :desc,
fragment( fragment(
"ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)",
t.search, t.search,
^trimmed_search ^trimmed_search
) )
} })
)
end end
@doc """ @doc """

View File

@ -75,6 +75,6 @@ defmodule CanneryWeb.TagLive.Index do
end end
defp display_tags(%{assigns: %{search: search, current_user: current_user}} = socket) do 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
end end

View File

@ -168,10 +168,10 @@ defmodule Cannery.ContainersTest do
tag_fixture(%{name: "bullet", desc: "pews brass shell"}, user_fixture()) tag_fixture(%{name: "bullet", desc: "pews brass shell"}, user_fixture())
# name # name
assert Containers.list_tags("bullet", current_user) == [tag_a] assert Containers.list_tags(current_user, search: "bullet") == [tag_a]
assert Containers.list_tags("bullets", current_user) == [tag_a] assert Containers.list_tags(current_user, search: "bullets") == [tag_a]
assert Containers.list_tags("hollow", current_user) == [tag_b] assert Containers.list_tags(current_user, search: "hollow") == [tag_b]
assert Containers.list_tags("hollows", current_user) == [tag_b] assert Containers.list_tags(current_user, search: "hollows") == [tag_b]
end end
test "get_tag!/2 returns the tag with given id", %{tag: tag, current_user: current_user} do test "get_tag!/2 returns the tag with given id", %{tag: tag, current_user: current_user} do