2
votes

I am trying to establish a one-to-many relationship. A user can create any number of posts. Phoenix 1.3, Ecto 2.2.1

#migrations
defmodule MyApp.Repo.Migrations.CreateUsersPosts do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :email, :string, null: false
      add :handle, :string, null: false
      add :password_hash, :string, null: false

      timestamps
    end
  end
...
  def change do
    create table(:posts) do
      add :title, :string
      add :users_id, references(:users, on_delete: :delete_all)
      add :content, :text

      timestamps()
    end
    create index(:posts, [:users_id])

  end
end

#models
defmodule MyApp.User do
  use MyApp.Web, :model

  @derive {Poison.Encoder, only: [:id, :email, :handle]}

  schema "users" do
    field :email, :string
    field :handle, :string
    field :password_hash, :string

    has_many :posts, MyApp.Post
    timestamps
  end
end

defmodule MyApp.Post do
  use Ecto.Schema

  schema "posts" do
    field :title, :string
    field :content, :string
    belongs_to :users, MyApp.User

    timestamps()
  end
end

#seeds.exs
MyApp.User.changeset(%MyApp.User{}, %{
  email: "[email protected]",
  handle: "me",
  password_hash: Comeonin.Bcrypt.hashpwsalt("me")})
|> MyApp.Repo.insert!

user = MyApp.Repo.get_by(MyApp.User, email: "[email protected]")
MyApp.Post.changeset(%MyApp.Post{}, %{
    title: "title",
    content: "content",
    users_id: user.id
})
|> MyApp.Repo.insert!

When I run the migrations and seed, I see the following when I query the post:

%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:loaded, "resources">,
  content: "content", title: "title",
  users: #Ecto.Association.NotLoaded<association :users is not loaded>,
  users_id: nil}

Even though I was successfully able to fetch the user id, I was unable to insert it into the users_id field. I am sure there is something simple that I am missing, what do I have to do to insert these relationships?

1

1 Answers

3
votes

First of all - foreign key like user_id should be named exactly this way, not users_id like you do have. Also please check how your MyApp.Post.changeset looks like. Propably you should add this new parameter in the list of optional allowed parameters. Otherwise it will be ignored by this function.