RuZ
RuZ

Reputation: 77

Elixir/Phoenix saving JSON to Postgres Database

I have Googled plenty for ways to do this.

I used the phx.gen generator to generate some CRUD. I want to create repos in my database and store Github activity for it.

My migration:

def change do
  create table(:coderepos) do
    add :name, :string
    add :description, :string
    add :repo_name, :string
    add :activity_data_raw, :jsonb
    timestamps()
  end
end

My model:

schema "coderepos" do
  field :activity_data_raw, :map, default: %{}
  field :name, :string
  field :description, :string
  field :repo_name, :string
  timestamps()
end

Upon creating my new repo (via the generated HTML):

#Ecto.Changeset<
  action: :insert,
  changes: %{
    description: "Blah",
    name: "Blah",
    repo_name: "blah"
  },
  errors: [activity_data_raw: {"is invalid", [type: :map, validation: :cast]}],
  data: #App.Integrations.CodeRepo<>,
  valid?: false
>

I get the changeset above by doing an IO.inspect(changeset) in the :error response of my create function in my controller.

My create function:

def create(conn, %{"code_repo" => code_repo_params}) do
  case Integrations.create_code_repo(code_repo_params) do
    {:ok, code_repo} ->
      conn
      |> put_flash(:info, "Code repo created successfully.")
      |> redirect(to: code_repo_path(conn, :show, code_repo))
    {:error, %Ecto.Changeset{} = changeset} ->
      render(conn, "new.html", changeset: changeset)
      IO.inspect(changeset)
  end
end

This is the piece of JSON I submit in my form (along with name, description and repo name):

[{"week": 1532822400, "total": 6, "days": [0, 6, 0, 0, 0, 0, 0]}]

(Just adding that saving to my DB works fine with other things I do in my app, so there isn't any problems there).

Postgres 10.4, Elixir 1.6.5 / OTP 20, Phoenix 1.3.3, Phoenix Ecto 3.2

Any help would be greatly appreciated!

Upvotes: 4

Views: 2304

Answers (1)

RuZ
RuZ

Reputation: 77

Thanks to @trevoke in the Elixir Slack, this is working now. You'll need to pass a map in (which is obvious I guess, though the other places I read made it sound like this is taken care of). Dogbert in the comments above was essentially saying the same thing.

In the create function:

raw = Map.get(code_repo_params, "activity_data_raw")
code_repo_params = Map.put(code_repo_params, "activity_data_raw", %{"data" => raw})

Upvotes: 1

Related Questions