我想编码两个模型,定义如下:
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 锁定了它。