You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ecto嵌套关联查询范围问题:筛选当前用户所属记录失败

Fixing the Ecto.Queryable Error When Fetching User-Specific League

First, let's break down why your current code is throwing the Protocol.UndefinedError:

  • When you preload :leagues for the user, user.leagues becomes a list of League structs, not a queryable (like the League schema module or an Ecto query).
  • Repo.get/2 expects its first argument to be a queryable (something Ecto can turn into a database query), not an in-memory list. That's why you're seeing the error about the Ecto.Queryable protocol not being implemented for a list.

Here are two clean solutions to fetch the league that belongs to the current user:

Instead of preloading all leagues first, query the League table directly with conditions for both the league ID and the current user's ID. This is more efficient because it only fetches the specific league you need from the database:

def show(conn, %{"id" => id}) do
  user_id = Map.get(Statcasters.Guardian.Plug.current_resource(conn), :id)
  # Fetch the league only if it belongs to the current user
  league = Repo.get_by(League, id: id, user_id: user_id)
  
  # Handle the case where the league doesn't exist or doesn't belong to the user
  if league do
    # Your existing logic here
  else
    # Return an error response, e.g., conn |> put_status(:not_found) |> json(%{error: "League not found"})
  end
end

Solution 2: Filter Preloaded List

If you already need the user's full list of leagues for other purposes, you can filter the preloaded list in memory instead of using Repo.get:

def show(conn, %{"id" => id}) do
  user_id = Map.get(Statcasters.Guardian.Plug.current_resource(conn), :id)
  user = Repo.get!(User, user_id) |> Repo.preload(:leagues)
  
  # Convert the string ID from params to integer (since league IDs are usually integers)
  league_id = String.to_integer(id)
  # Find the matching league in the preloaded list
  league = Enum.find(user.leagues, fn league -> league.id == league_id end)
  
  # Handle missing league case as above
end

Note: Solution 1 is better for performance when you only need the single league, as it avoids loading all of the user's leagues into memory.

内容的提问来源于stack exchange,提问作者Bitwise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:42:12