Hello,
I've tried to follow this gist, but it seems that Ecto is
keeping adding id = NULL to the query even if id wasn't specified in the
params. The outcome is that PostgreSQL is shouting about failing constraints,
instead of generating UUID. When I add record manually, without specyfing id in the VALUES claues, UUID is properly generated by PostgreSQL.
I have to manually generate UUID in before_insert callback (like here:
http://stackoverflow.com/questions/30004008/setting-up-phoenix-framework-and-ecto-to-use-uuids-how-to-insert-the-generated) this however seems to be very redundant. Can anyone help? How can I disable appending id to INSERT queries? (it really doesn't make any sense)
Please take look at the stack trace:
[info] POST /api/rest/v1/input/stream/http
[info] Processing by MyApp.Input.Stream.HTTPController.create/2
Parameters: %{"format" => "json", "http" => %{"location" => "http://wp.pl"}}
Pipelines: [:api]
[debug] BEGIN [] OK query=126.8ms
[debug]
INSERT INTO "input_stream_http" ("id", "inserted_at", "location",
"updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [nil, {{2015, 6,
20}, {20, 32, 45, 0}}, "http://wp.pl", {{2015, 6, 20}, {20, 32, 45, 0}}]
ERROR query=9.4ms
[debug] ROLLBACK [] OK query=0.4ms
[info] Sent 500 in 291ms
[error] #PID<0.289.0> running MyApp.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /api/rest/v1/input/stream/http
** (exit) an exception was raised:
** (Postgrex.Error) ERROR (not_null_violation): null value in column "id" violates not-null constraint
(ecto) lib/ecto/adapters/sql.ex:210: Ecto.Adapters.SQL.log_and_check/7
(ecto) lib/ecto/adapters/sql.ex:433: Ecto.Adapters.SQL.model/5
(ecto) lib/ecto/repo/model.ex:34: anonymous fn/10 in Ecto.Repo.Model.insert/4
(ecto) lib/ecto/adapters/sql.ex:485: Ecto.Adapters.SQL.transaction/3
(ecto) lib/ecto/repo/model.ex:206: Ecto.Repo.Model.with_transactions_if_callbacks/6
(radio_kit_mixer) web/controllers/input/stream/http_controller.ex:18: MyApp.Input.Stream.HTTPController.create/2
(radio_kit_mixer) web/controllers/input/stream/http_controller.ex:1:
MyApp.Input.Stream.HTTPController.phoenix_controller_pipeline/2
(radio_kit_mixer) lib/phoenix/router.ex:297: MyApp.Router.dispatch/2
Model definition:
def model do
quote do
use Ecto.Model
@primary_key {:id, Ecto.UUID, read_after_writes: true}
@foreign_key_type Ecto.UUID
end
end
defmodule MyApp.Input.Stream.HTTP do
use MyApp.Web, :model
schema "input_stream_http" do
field :location, :string
timestamps
end
@required_fields ~w(location)
@optional_fields ~w()
@doc """
Creates a changeset based on the `model` and `params`.
If `params` are nil, an invalid changeset is returned
with no validation performed.
"""
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
Migration
defmodule MyApp.Repo.Migrations.CreateInput.Stream.HTTP do
use Ecto.Migration
def change do
execute "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\""
create table(:input_stream_http, primary_key: false) do
add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")
add :location, :string, null: false
timestamps
end
end
end
I am using phoenix 0.13.1 and ecto 0.12.0-rc.
Marcin