Ecto.Changeset.cast/4 中没有函数子句匹配

Posted

技术标签:

【中文标题】Ecto.Changeset.cast/4 中没有函数子句匹配【英文标题】:no function clause matching in Ecto.Changeset.cast/4 【发布时间】:2020-10-21 21:56:06 【问题描述】:

我遇到了 naivedatetime 的转换错误。有人可以帮我解锁吗?

这是我正在尝试执行的 POST 请求: 网址:http://localhost:4000/api/workingtimes/1

主体:

"开始": "2019-08-21 07:27:00", “结束”:“2020-09-20 07:27:00”

这是我的架构:

 defmodule TimeManager.Workingtimes.Workingtime do
  use Ecto.Schema
  import Ecto.Changeset

  schema "workingtimes" do
    field :start, :naive_datetime
    field :end, :naive_datetime
    belongs_to :user, TimeManager.Users.User

    timestamps()
  end

  @doc false
  def changeset(workingtime, attrs) do
    workingtime
    |> cast(attrs, [:start, :end, :user_id])
    |> validate_required([:start, :end, :user_id])
    |> assoc_constraint(:user)
  end
end

这是我在控制器中的创建函数:

  def create(conn, workingtime_params) do
    with :ok, %Workingtime = workingtime <- Workingtimes.create_workingtime(workingtime_params) do
      conn
      |> put_status(:created)
      |> put_resp_header("location", Routes.workingtime_path(conn, :show, workingtime))
      |> render("workingtime.json", workingtime: workingtime)
    end
  end

最后是我的 workingtimes.ex 中的 create_workingtime 函数

  def create_workingtime(attrs \\ %) do
    %"start" => starttime, "end" => endtime, "user_id"=>user_id  = attrs
    :ok, naivestart = NaiveDateTime.from_iso8601(starttime)
    :ok, naiveend = NaiveDateTime.from_iso8601(endtime)
    attrs = %"start" => naivestart, "end"=>naiveend, "user_id"=>user_id
  
    Workingtime
    |> Workingtime.changeset(attrs)
    |> Repo.insert()
  end

日志中的错误是:

(退出)引发异常: ** (FunctionClauseError) (ecto 3.5.2) lib/ecto/changeset.ex:461: Ecto.Changeset.cast(TimeManager.Workingtimes.Workingtime, %"end" => ~N[2020-10-21 19:45:24.879000], "开始" => ~N[2020-10-21 19:45:24.879000], "user_id" => "1", [:start, :end, :user_id], []) (time_manager 0.1.0) lib/time_manager/workingtimes/workingtime.ex:16: TimeManager.Workingtimes.Workingtime.changeset/2 (time_manager 0.1.0) lib/time_manager/workingtimes.ex:63: TimeManager.Workingtimes.create_workingtime/1 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:16: TimeManagerWeb.WorkingtimeController.create/2 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:1: TimeManagerWeb.WorkingtimeController.action/2 (time_manager 0.1.0) lib/time_manager_web/controllers/workingtime_controller.ex:1: TimeManagerWeb.WorkingtimeController.phoenix_controller_pipeline/2

【问题讨论】:

【参考方案1】:

Ecto.Changeset.cast/4 将模式结构作为第一个参数,而不是模式模块。在您的 create_workingtime/1 函数中,尝试更改为:

%Workingtime
|> Workingtime.changeset(attrs)
|> Repo.insert()

【讨论】:

【参考方案2】:

发现了问题,在 create_workingtime 函数中是:%Workingtime 而不是 Workingtime

  def create_workingtime(attrs \\ %) do
    %"start" => starttime, "end" => endtime, "user_id"=>user_id  = attrs
    :ok, naivestart = NaiveDateTime.from_iso8601(starttime)
    :ok, naiveend = NaiveDateTime.from_iso8601(endtime)
    attrs = %"start" => naivestart, "end"=>naiveend, "user_id"=>user_id
  
    %Workingtime
    |> Workingtime.changeset(attrs)
    |> Repo.insert()
  end

【讨论】:

深入了解它的好工作。这是一个常见且容易落入的陷阱。这就是@Brett Beatty 所指出的——这很大程度上取决于一个简单的%:没有它,你只是指一个模块名称(Workingtime)。添加它,您指的是结构(%Workingtime)。

以上是关于Ecto.Changeset.cast/4 中没有函数子句匹配的主要内容,如果未能解决你的问题,请参考以下文章

代码中没有错误,但尝试更新时表中没有发生变化

Eclipse C++ 问题:没有二进制文件(但没有编译器错误),没有类(但在类层次结构中没有条目)

Vue Prop 没有初始化器,也没有在构造函数中明确赋值

Colab 中没有名为“statsmodels.tsa.arima”的模块,但 Pycharm 中没有

为啥eclipse中没有server

为啥 Rails 应用程序没有拆分,业务逻辑没有转移到 gem 中? [关闭]