title: Getting Ecto to pass foreign keys
body: <p>I'm working with Ecto (with Postgres) for the first time and I have the following two schemas (both somewhat simplified):</p>
  
  <pre><code>defmodule RailroadServer.Database.RailroadSystem do
    @moduledoc """
    Schema for an entire railroad system.
    """
    use Ecto.Schema
    import Ecto.Changeset
    alias RailroadServer.Database
  
    schema "railroad_systems" do
      field :railroad_system_name, :string
      has_many :depos, Database.Depo
    end
  
    @fields ~w(railroad_system_name)a
  
    def changeset(data, params \\ %{}) do
      data
      |&gt; cast(params, @fields)
      |&gt; validate_required([:railroad_system_name])
      |&gt; validate_length(:railroad_system_name, max: 50)
    end
  end
  </code></pre>
  
  <pre><code>defmodule RailroadServer.Database.Depo do
    @moduledoc """
    Schema for a node that stores trains.
    """
    use Ecto.Schema
    import Ecto.Changeset
    alias RailroadServer.Database
  
    schema "depos" do
      field :capacity, :integer
      field :depo_uuid, :string
      field :depo_name, :string
      belongs_to :railroad_system, Database.RailroadSystem
    end
  
    @fields ~w(capacity depo_uuid depo_name)a
  
    def changeset(data, params \\ %{}) do
      data
      |&gt; cast(params, @fields)
      |&gt; validate_required([:capacity, :depo_uuid, :depo_name])
      |&gt; validate_number(:capacity, greater_than: 0)
      |&gt; validate_length(:depo_name, max: 50)
      |&gt; validate_length(:depo_uuid, max: 50)
      |&gt; foreign_key_constraint(:railroad_system_id)
    end
  end
  </code></pre>
  
  <p>Based on these migrations:</p>
  
  <pre><code>defmodule RailroadServer.Database.Repo.Migrations.CreateRailroadSystems do
    use Ecto.Migration
  
    def change do
      create table(:railroad_systems) do
        add :railroad_system_name, :varchar, null: false, size: 50
      end
  
      create unique_index("railroad_systems", [:railroad_system_name])
    end
  end
  </code></pre>
  
  <pre><code>defmodule RailroadServer.Database.Repo.Migrations.CreateDepos do
    use Ecto.Migration
  
    def change do
      create table(:depos) do
        add :railroad_system_id, references("railroad_systems"), null: false
        add :depo_uuid, :varchar, size: 50, null: false
        add :depo_name, :varchar, size: 50, null: false
        add :capacity, :integer, null: false
      end
  
      create index("depos", [:railroad_system_id])
      create index("depos", [:depo_uuid], unique: true)
      create index("depos", [:depo_name], unique: true)
    end
  end
  </code></pre>
  
  <p>Which I'm constructing with the following code:</p>
  
  <pre><code>  def insert_railway_system(system_name, depos) do
      cs = %RailroadSystem{}
      |&gt; RailroadSystem.changeset(%{railroad_system_name: system_name})
      |&gt; put_assoc(:depos, create_depos(depos))
  
      if cs.valid? do
        Repo.insert(cs)
      else
        {:error, cs}
      end
    end
  
    _ = """
    Uses a list of depo nodes to construct a list of depo changeset.
    """
    defp create_depos(depos) do
      Enum.map(depos, fn(depo) -&gt; Depo.changeset(%Depo{}, depo) end)
    end
  </code></pre>
  
  <p>However, when I run this function (with data that produces a valid changeset), I get a NULL column error because the foreign key for the railway system in the depo struct doesn't exist. How do I make sure that Ecto passes that foreign key?</p>
  
  <p>The output: </p>
  
  <pre><code>19:06:07.401 [debug] QUERY OK db=0.8ms
  begin []
  
  19:06:07.406 [debug] QUERY OK db=0.6ms
  INSERT INTO "railroad_systems" ("railroad_system_name") VALUES ($1) RETURNING "id" ["test Can insert railway system"]
  
  19:06:07.409 [debug] QUERY ERROR db=2.7ms
  INSERT INTO "depos" ("capacity","depo_name","depo_uuid") VALUES ($1,$2,$3) RETURNING "id" [23, "A depo", "d387a91b-db77-4758-87ed-9951d5c2de8a"]
  
  19:06:07.410 [debug] QUERY OK db=0.1ms
  rollback []
  
  
    1) test Can insert railway system (RailroadServer.DatabaseTest)
       apps/railroad_server/test/railroad_server/database_test.exs:9
       ** (Postgrex.Error) ERROR 23502 (not_null_violation) null value in column "railroad_system_id" violates not-null constraint
  
           table: depos
           column: railroad_system_id
  
       Failing row contains (3, null, d387a91b-db77-4758-87ed-9951d5c2de8a, A depo, 23).
       stacktrace:
         (ecto_sql) lib/ecto/adapters/sql.ex:621: Ecto.Adapters.SQL.raise_sql_call_error/1
         (ecto) lib/ecto/repo/schema.ex:649: Ecto.Repo.Schema.apply/4
         (ecto) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
         (ecto) lib/ecto/association.ex:927: Ecto.Association.BelongsTo.on_repo_change/5
         (ecto) lib/ecto/association.ex:413: Ecto.Association.on_repo_change/7
         (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
         (ecto) lib/ecto/association.ex:392: Ecto.Association.on_repo_change/4
         (ecto) lib/ecto/repo/schema.ex:811: Ecto.Repo.Schema.process_parents/4
         (ecto) lib/ecto/repo/schema.ex:242: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
         (ecto) lib/ecto/association.ex:662: Ecto.Association.Has.on_repo_change/5
         (ecto) lib/ecto/association.ex:432: anonymous fn/8 in Ecto.Association.on_repo_change/7
         (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
         (ecto) lib/ecto/association.ex:428: Ecto.Association.on_repo_change/7
         (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
         (ecto) lib/ecto/association.ex:392: Ecto.Association.on_repo_change/4
         (ecto) lib/ecto/repo/schema.ex:837: Ecto.Repo.Schema.process_children/5
         (ecto) lib/ecto/repo/schema.ex:914: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
         (ecto_sql) lib/ecto/adapters/sql.ex:890: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
         (db_connection) lib/db_connection.ex:1415: DBConnection.run_transaction/4
         (railroad_server) lib/railroad_server/database.ex:61: RailroadServer.Database.insert_railway_system/4
  
  </code></pre>
  
  <p>Versions:
  Elixir - 1.9.0
  Ecto - 3.17
  Postgrex - 0.14.3
  Prosgres - 11.4</p>