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 ![]()
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
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
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 ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








