1

我想编码两个模型,定义如下:

web/models/vote.ex

defmodule LetsPlan.Vote do
  use LetsPlan.Web, :model

  alias LetsPlan.Availability
  import LetsPlan.Utils, only: [to_ecto_date: 1]

  @derive {Poison.Encoder, only: [:name, :availabilities]}
  schema "votes" do
    field :name, :string, null: false
    belongs_to :event, LetsPlan.Event
    embeds_many :availabilities, LetsPlan.Availability

    timestamps
  end
end

web/models/availability.ex

defmodule LetsPlan.Availability do
  use LetsPlan.Web, :model

  @derive {Poison.Encoder, only: [:from, :to]}
  embedded_schema do
    field :from, Ecto.Date
    field :to, Ecto.Date
  end
end

如果我Poison.encode在脚本中使用并通过 iex 执行它,它可以正常工作:

alias LetsPlan.Repo
alias LetsPlan.Event

# Same code as in the controller
event = Event |> Repo.get(1)
votes = (event |> Repo.preload(:votes)).votes
votes |> Poison.encode |> IO.puts  # {:ok, "..."}

但是,当我在控制器中执行完全相同的操作时,它会出现错误{:invalid, {nil, "posts"}}。我真的无法理解有什么区别。以下是控制器的相关操作:

def create(conn, %{"event_id" => event_id, "vote" => vote_params}) do
  changeset =
    %Vote{}
    |> Vote.changeset(Map.put(vote_params, "event_id", event_id))
  event = Event |> Repo.get!(event_id)

  if changeset.valid? do
    Repo.insert(changeset)
    votes = (event |> Repo.preload(:votes)).votes
    votes |> inspect |> IO.puts

    case Poison.encode votes do
      {:ok, payload} -> Endpoint.broadcast("events:#{event_id}", "new_votes",
                                           payload)
      {:error, reason} -> reason |> inspect |> IO.puts
    end

    conn
    |> put_flash(:info, "Availabilities added.")
    |> redirect(to: event_path(conn, :show, event))
  else
    render conn, "new.html", changeset: changeset, event: event
  end
end

注意:我没有使用 Poison 2.1.0,而是 1.5.2 版,因为 Ecto 锁定了它。

4

0 回答 0