Hey there,
I am trying to find an elegant way to populate a field on a join table in a json response.
I got the following schemas:
schema "characters" do
field :name, :string
has_many :characters_skills, Skill
has_many :skills, through: [:characters_skills, :skill]
end
schema "talents" do
field :name, :string
field :times_taken, :string, virtual: true
has_many :characters_talents, Character.Talent
has_many :characters, through: [:characters_talents, :character]
timestamps()
end
schema "characters_talents" do
belongs_to(:character, Character, primary_key: true)
belongs_to(:talent, Abilities.Talent, primary_key: true)
field :times_taken, :integer
timestamps()
end
Now in my response I don’t want characters_talents
but rather just talents
containing times_taken
.
My current approach is this:
import Ecto.Query
from(c in Character)
|> preload([:talents])
|> join(:inner, [c], t in assoc(c, :talents))
|> join(:inner, [c, t], ct in assoc(c, :characters_talents))
|> select_merge([c, t, ct], %{talents: merge(t, %{times_taken: ct.times_taken})})
which works fine, as soon as I switch to :left_join
because t
might be empty merge/2
raises.
Is the anything I don’t see? Anything I could do more efficient? I am asking especially because my character
schema has at least 5 more relations like this.
Thanks,
Nick
Also might be worse mentioning, that I opened a proposal here:
https://groups.google.com/g/elixir-ecto/c/vLAfANvnVy4/m/wS8TSMySBQAJ
So merge/2
might except nil
values.