【问题标题】:Value in where cannot be cast to type :id in query无法将 where 中的值强制转换为类型 :id 在查询中
【发布时间】:2018-10-11 23:24:14
【问题描述】:

我正在尝试将我的 cmets 加入一个帖子,以便当用户访问 /posts/:id/cmets 时,他/她可以查看与该帖子关联的所有 cmets。

这是我的路由器

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

然后是我的帖子控制器:

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

我的评论控制器:

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

当我尝试在 post/:id/cmets 中添加新评论时,它会抛出此错误:

(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

这是我的 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

还有我的 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

从错误中,我认为ecto试图将整个请求参数作为p.id传递,但它不应该是这样,请问我该如何纠正它?我对此进行了很多研究并尝试了一些更改,但得到了不同的错误。

【问题讨论】:

  • 这是我最初的评论控制器:def create(conn, %{"post_id" =&gt; id, "comment_params" =&gt; comment_params}) do post = Repo.get(Post, id) comment_changeset = Ecto.build_assoc(post, :comment, comment_params) Repo.insert(comment_changeset) 但这给了我这个错误:[debug] ** (Phoenix.ActionClauseError) could not find a matching MyappWeb.CommentController.create clause. This typically happens when there is a parameter mismatch but may also happen when any of the other action arguments do not match.

标签: elixir phoenix-framework ecto


【解决方案1】:

问题就在这里:

Repo.get(Post, comment_params)

注释参数是控制器接收到的,这就是您在错误消息中看到的:

%{"description" => "bitcoin", "post_id" => "2", "name" => "ethereum"}

OTOH Repo.get/3 期望帖子 ID 作为第二个字段。这样的事情会起作用:

def create(conn, %{"post_id" => id} = comment_params) do
  post = Repo.get(Post, String.to_integer(id))

【讨论】:

  • 我尝试过,但在发布到 posts/:id/cmets 时出现新错误:**(FunctionClauseError) no funtion clause matching in Ecto.drop_meta/1
  • 这是不同的东西,与原始问题完全无关。您可能会发布另一个问题来询问此问题,指定您发布的数据、此错误来自哪一行以及所有这些内容。
猜你喜欢
  • 2021-03-08
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2017-08-25
  • 1970-01-01
  • 2012-08-29
  • 2018-05-24
  • 1970-01-01
相关资源
最近更新 更多