title: Elixir Ecto: How to validate foreign key constraint?
body: <p>I'm playing with Elixir and the Phoenix web framework, but now I'm stuck on trying to validate a foreign key constraint. So, given a model <code>Post</code> with <em>many comments</em>, I wrote the <code>Comment</code> model as follows:</p>
  
  <pre><code>defmodule MyApp.Comment do
    use MyAPp.Web, :model
  
    schema "comments" do
      field :body, :text
      belongs_to :post, MyApp.Post
  
      timestamps
    end
  
    @required_fields ~w(body post_id)
    @optional_fields ~w()
  
    def changeset(model, params \\ :empty) do
      model
      |&gt; cast(params, @required_fields, @optional_fields)
      |&gt; foreign_key_constraint(:post_id)
    end
  end
  </code></pre>
  
  <p>and its unit test:</p>
  
  <pre><code>defmodule MyApp.CommentTest do
    # [...]
    test "changeset with non existent post" do
      attrs = %{
        body: "A comment."
        post_id: -1 # some non-existent id?
      }
      refute Comment.changeset(%Comment{}, attrs).valid?
      assert {:post_id, "does not exist"} in errors_on(%Comment{}, %{})
    end
  end
  </code></pre>
  
  <p>According to <a href="http://hexdocs.pm/ecto/Ecto.Changeset.html#foreign_key_constraint/3" rel="noreferrer">http://hexdocs.pm/ecto/Ecto.Changeset.html#foreign_key_constraint/3</a>:</p>
  
  <blockquote>
    <p>The foreign key constraint works by relying on the database to check
    if the associated model exists or not. This is useful to guarantee
    that a child will only be created if the parent exists in the database
    too.</p>
  </blockquote>
  
  <p>I expected that the code I wrote worked, instead it only checks for presence (as defined in <code>@required_fields ~w(body post_id)</code>). I'm not excluding I did something wrong or misunderstood the statement in the docs.</p>
  
  <p>Has anyone already stumbled upon this?</p>
  
  <p><strong>UPDATE:</strong>
  For completeness, here's the migration:</p>
  
  <pre><code>def change do
    create table(:comments) do
      add :body, :text
      add :post_id, references(:posts)
  
      timestamps
    end
  
    create index(:comments, [:post_id])
  end
  </code></pre>