1

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.

rubik
  • 8,814
  • 9
  • 58
  • 88
  • What does the line `votes |> inspect |> IO.puts` print? (Tip: `|> inspect |> IO.puts` is the same as `|> IO.inspect`) – Dogbert Mar 27 '16 at 09:20
  • @Dogbert Thanks for the tip! It prints `{:error, {:invalid, {nil, “votes”}}}`. It should print `{:ok, "[json here]"}`, just like in the script. – rubik Mar 27 '16 at 09:21
  • Are you sure `votes` contains that or is that `reason`? – Dogbert Mar 27 '16 at 09:26
  • @Dogbert I'm sorry, that was reason. Votes are like this: https://gist.github.com/rubik/f32ce95183305f406b5e – rubik Mar 27 '16 at 09:29
  • @Dogbert I'm puzzled here. Now it works. I didn't change anything! I just restarted the server?! That shouldn't have anything to do with Poison... – rubik Mar 27 '16 at 09:37

0 Answers0