Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is this Ecto Constraint Error trying to tell me?

** (Ecto.ConstraintError) constraint error when attempting to insert model:

    * foreign_key: matches_person_id_fkey

Here is my schema and migration:

def change do
  create table(:matches) do
    add :percentage, :float
    add :person_id, references(:persons)
    add :star_id, references(:stars)

    timestamps
  end
  create index(:matches, [:person_id])
end

schema "matches" do
  field :percentage, :float
  belongs_to :person, Person
  belongs_to :star, Star

  timestamps
end

The changeset I am using when calling Repo.insert(changeset) is:

%Ecto.Changeset{action: nil,
 changes: %{percentage: 0.513657, person_id: 55, star_id: 1}, constraints: [],
 errors: [], filters: %{},
 model: %App.Match{__meta__: #ecto.Schema.Metadata<:built>, id: nil,
  inserted_at: nil, percentage: nil,
  person: #ecto.Association.NotLoaded<association :person is not loaded>,
  person_id: nil,
  star: #ecto.Association.NotLoaded<association :star is not loaded>,
  star_id: nil, updated_at: nil}, optional: [], opts: [],
 params: %{"percentage" => 0.513657, "person_id" => 55, "star_id" => 1},
 prepare: [], repo: nil, required: [:percentage, :person_id, :star_id],
 types: %{id: :id, inserted_at: Ecto.DateTime, percentage: :float,
   person_id: :id, star_id: :id, updated_at: Ecto.DateTime}, valid?: true,
 validations: []}

I'm not sure what happened or if I made a change along the way because this was working previously. The error seems to suggest I need a person_id, which I do.

Edit: As requested the function call I'm making for the match insert

...
Repo.transaction(fn ->
  case Repo.insert(person_changeset) do
  {:ok, person} ->
     Match.create(person.id)
  {:error, _}
     Repo.rollback(:no_bueno)
  end
end)

def create(person_id) do
  ...
  params = %{"person_id" => person.id, "percentage" => percentage, "star_id" => star.id}
  changeset = __MODULE__.changeset(%__MODULE__{}, params)
  case Repo.insert(changeset) do
  {:ok, _person} ->
     IO.puts "success"
  {:error, _changeset} ->
     Repo.rollback(:no_bueno)
  end
end
like image 517
Alejandro Huerta Avatar asked Jan 18 '16 14:01

Alejandro Huerta


1 Answers

This error is telling you that the person with id 55 does not exist.

Somewhat related, in your migration, the following is not required:

create index(:matches, [:person_id])

The index will be automatically created when you references/2:

add :person_id, references(:persons)

If you want to populate the errors in the changeset, you need to add foreign_key_constraint/3 to your changeset:

cast(match, params, ~w(person_id), ~w())
|> foreign_key_constraint(:person_id)

While not directly related to the question, it looks like you might be using Repo in your model. Please see Should I use Ecto.Repo in Controller or Model for Elixir Phoenix?

like image 60
Gazler Avatar answered Oct 23 '22 08:10

Gazler