Value in where cannot be cast to type :id in query

I’m trying to join my comments to a post, so that when a user visits /posts/:id/comments, he/she can get to view all the comments associated with the post.

This is my router

resources "/posts", PostController, except: [:new, :edit] do
  resources "/comments", CommentController, except: [:new, :edit]
end

Then my Post Controller:

def index(conn, _params) do
    post = Posts.list_posts()
    render(conn, "index.json", posts: posts)
  end

  def create(conn, post_params) do
    with {:ok, %Post{} = post} <-Posts.create_post(post_params) do #create_post is from post context
      conn
      |> put_status(:created)
      |> put_resp_header("location", post_path(conn, :show, post))
      |> render("show.json", post: post)
    end
  end

  def show(conn, %{"id" => id}) do
    post = Repo.get!(Post, id)
    comment_changeset = Comment.changeset(%Comment{})
    render(conn, "show.json", post: post, comment_changeset: comment_changeset)
  end

My comment controller:

  def index(conn, _params) do
    comment= Comment.list_comment() #from comment context
    render(conn, "index.json", comments: comments)
  end

  def create(conn, comment_params) do
    post = Repo.get(Post, comment_params)
    comment_changeset = Ecto.build_assoc(post, :comment, comment_params)
    Repo.insert(comment_changeset)

      conn
      |> put_status(:created)
      |> render("show.json")
  end

  def show(conn, %{"id" => id}) do
    comment = Comment.get_comment!(id) #from comment context
    render(conn, "show.json", comment: comment
  end

When I try to add new comment in post/:id/comments, it throws this error:

(Ecto.Query.CastError) deps/ecto/lib/ecto/repo/queryable.ex:348: value `%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"}` in `where` cannot be cast to type :id in query:

from m in Myapp.Posts.Post,
  where: p.id == ^%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"},
  select: p

This is my Myapp.Posts.Post:

schema "posts" do
    field :description, :string
    field :name, :string
    has_many :comments, Myapp.Comments.Comment
    field :body, :string

    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:name, :description, :body])
    |> validate_required([:name, :body ])
  end

And my Myapp.Comments.Comment

  schema "comments" do
    field :description, :string
    field :name, :string
    belongs_to :market, Myapp.Posts.Post

    timestamps()
  end

  @doc false
  def changeset(comment, attrs) do
    pair
    |> cast(attrs, [:name, :description])
    |> validate_required([:name, :description])
  end

From the error, I think ecto is trying to pass the entire request parameters as p.id, but it shouldn’t be so, please how can I correct it? I have done many researches on it and tried some changes but got different errors.

Hi, could you post the full stack trace of the error?

from m in Myapp.Posts.Post,
  where: p.id == ^%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"},
  select: p

could you elaborate on this snippet?

1 Like
[info] POST /api/v1/posts/2/comments
[debug] Processing with MyappWeb.CommentController.create/2
  Parameters: %{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"}
  Pipelines: [:api]
[info] Sent 400 in 14ms
[debug] ** (Ecto.Query.CastError) deps/ecto/lib/ecto/repo/queryable.ex:348: value `%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"}` in `where` cannot be cast to type :id in query:

from m in Myapp.Posts.Post,
  where: p.id == ^%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"},
  select: p

    (elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir) lib/enum.ex:1418: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/repo/queryable.ex:124: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
    (ecto) lib/ecto/repo/queryable.ex:70: Ecto.Repo.Queryable.one/4
    (myapp) lib/myapp_web/controllers/comment_controller.ex:17: MyappWeb.CommentController.create/2
    (myapp) lib/myapp_web/controllers/comment_controller.ex:1: MyappWeb.CommentController.action/2
    (myapp) lib/myapp_web/controllers/comment_controller.ex:1: MyappWeb.CommentController.phoenix_controller_pipeline/2
    (myapp) lib/myapp_web/endpoint.ex:1: MyappWeb.Endpoint.instrument/4
    (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1

Thanks

1 Like

This is your problem. This should be comment_params["post_id"].

3 Likes