aNerdInTheHand

aNerdInTheHand

How do I insert items with associations into my database via iex?

N.B. I don’t seem to have permission to post in the Phoenix section :woman_shrugging:

Background

I’m learning Phoenix and my relational database skills are a bit rusty to say the least. I’m trying to create a data structure for creating musical chord progressions, whereby a Progression has a many to many association with a Chord. I’m loosely following this guide. To do this I have the following schema (please tell me if my design is generally awful by the way!):

# create_chords migration
defmodule Chordwitch.Repo.Migrations.CreateChords do
  use Ecto.Migration

  def change do
    create table(:chords) do
      add :numeral, :string
      add :extension, :string
      add :tonality, :string
      add :function, :string
      add :comments, :text
      add :altered, :boolean, default: false, null: false

      timestamps()
    end
  end
end
# lib/chords/chord.ex
defmodule Chordwitch.Chords.Chord do
  use Ecto.Schema
  import Ecto.Changeset
  alias Progressions.Progression

  schema "chords" do
    field :altered, :boolean, default: false
    field :comments, :string
    field :extension, :string
    field :function, :string
    field :numeral, :string
    field :tonality, Ecto.Enum, values: [:major, :minor, :neutral]
    many_to_many :progressions, Progression, join_through: "progression_chords"

    timestamps()
  end

  @doc false
  def changeset(chord, attrs) do
    chord
    |> cast(attrs, [:numeral, :extension, :tonality, :function, :comments, :altered])
    |> validate_required([:numeral, :extension, :tonality, :function, :comments, :altered])
  end
end

# create_progressions migration
defmodule Chordwitch.Repo.Migrations.CreateProgressions do
  use Ecto.Migration

  def change do
    create table(:progressions) do
      add :name, :string
      add :tags, {:array, :string}

      timestamps()
    end
  end
end
# lib/progressions/progression.ex
defmodule Chordwitch.Progressions.Progression do
  use Ecto.Schema
  import Ecto.Changeset
  alias Chords.Chord

  schema "progressions" do
    field :name, :string
    field :tags, {:array, :string}
    many_to_many :chords, Chord, join_through: "progression_chords"

    timestamps()
  end

  @doc false
  def changeset(progression, attrs) do
    progression
    |> cast(attrs, [:name, :tags])
    |> validate_required([:name, :tags])
  end
end

As you can see I’ve also created a relationship table for progression_chords with many_to_many associations in both my chord and progression schema. The migration for progression_chords looks like this:

defmodule Chordwitch.Repo.Migrations.CreateProgressionChords do
  use Ecto.Migration

  def change do
    create table(:progression_chords) do
      add :progression_id, references(:progressions)
      add :chord_id, references(:chords)
      add :index, :integer
    end
  end
end

I’m trying to test this out by running my application in iex and doing the following:

alias Chordwitch.Chords.Chord
Chordwitch.Chords.Chord
iex(2)> alias Chordwitch.Progressions.Progression
Chordwitch.Progressions.Progression
iex(3)> alias Chordwitch.Repo
Chordwitch.Repo
iex(4)> p = %Progression{name: "iex Rock"}
%Chordwitch.Progressions.Progression{
  __meta__: #Ecto.Schema.Metadata<:built, "progressions">,
  id: nil,
  name: "iex Rock",
  tags: nil,
  chords: #Ecto.Association.NotLoaded<association :chords is not loaded>,
  inserted_at: nil,
  updated_at: nil
}
iex(5)> p = Repo.insert!(p)

Problem

When I run that last command and try and insert my progression (before building any associations), I get the following error:

** (UndefinedFunctionError) function Chords.Chord.__schema__/1 is undefined (module Chords.Chord is not available)
    Chords.Chord.__schema__(:primary_key)
    (ecto 3.10.1) lib/ecto/changeset/relation.ex:155: Ecto.Changeset.Relation.change/3
    (ecto 3.10.1) lib/ecto/changeset/relation.ex:526: anonymous fn/4 in Ecto.Changeset.Relation.surface_changes/3
    (elixir 1.14.4) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto 3.10.1) lib/ecto/changeset/relation.ex:513: Ecto.Changeset.Relation.surface_changes/3
    (ecto 3.10.1) lib/ecto/repo/schema.ex:344: Ecto.Repo.Schema.do_insert/4
    (ecto 3.10.1) lib/ecto/repo/schema.ex:273: Ecto.Repo.Schema.insert!/4

This error is the reason I have alias ed Chord in the Progression module and vice versa, it’s not something that was in the guide.

Sorry for the long post but any pointers would be appreciated.

Marked As Solved

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Welcome!

New users need to have their posts validated by a moderator as an anti spam measure.

defmodule Chordwitch.Progressions.Progression do
  use Ecto.Schema
  import Ecto.Changeset
  alias Chords.Chord

This is your bug. You have done alias Chords.Chord and therefore this line here many_to_many :chords, Chord aliases to many_to_many :chords, Chords.Chord, but the module is Chordwitch.Chords.Chord

You should have alias Chordwitch.Chords.Chord instead, or just don’t alias and use the full module name.

Also Liked

aNerdInTheHand

aNerdInTheHand

D’oh! Yes of course that was it, and I should have known as I’d aliased correctly in iex! But thanks very much for the quick reply to a confused newbie :slight_smile:

Where Next?

Popular in Questions Top

skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement