I want to encode two models, defined below:
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
If I use Poison.encode
inside a script and execute it through iex, it works fine:
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, "..."}
However, when I do the exact same thing in the controller, it errors out with {:invalid, {nil, "posts"}}
. I really cannot understand what's the difference. Here is the relevant action from the controller:
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
NOTE: I'm not using Poison 2.1.0, but version 1.5.2, since Ecto locks it.