I’m struggling to understand the purpose of has many through and the many to many associations. The 2 things I’m struggling with is inserting an associated record and querying through an association.
This is my schema setup:
schema "users" do
field(:email, :string)
field(:password, :string)
has_many :users_profiles, UserProfile
has_many :profiles, through: [:users_profiles, :profiles]
end
schema "profiles" do
field(:description, :string)
field(:is_active, :boolean)
has_many :users_profiles, UserProfile
has_many :users, through: [:users_profiles, :users]
end
schema "users_profiles" do
field(:role, :string)
belongs_to(:user, User)
belongs_to(:profile, Profile)
end
Inserting:
When inserting a profile for a user a record needs to be added to the join table users_profiles. It seems to me that ecto doesn’t help here I couldn’t use put_assoc, cast_assoc or build_assoc so my solution was to use Ecto.Multi. Is this the correct way?
def create_profile(%User{} = user, attrs \\ %{}) do
Multi.new()
|> Multi.insert(:profile, Profile.changeset(%Profile{}, attrs))
|> Multi.run(:user_profile, fn _, %{profile: %{id: id}} ->
UsersProfiles.create_user_profile_owner(%{user_id: user.id, profile_id: id})
end)
|> Repo.transaction()
end
Querying:
When querying using the association via Repo.preload it causes 2 queries. First way uses the has_many :profiles, through: [:users_profiles, :profiles]
user |> Repo.preload(:profiles)
or alternatively using the has_many :users_profiles association and the belongs_to association on users_profiles schema.
user |> Repo.preload(users_profiles: [:profile])
So I instead just wrote a join query as that way it would only be a single query, like so:
def profiles(user) do
query =
from p in Profile,
join: up in UserProfile,
on: up.profile_id == p.id,
where: up.user_id == ^user.id
Repo.all(query)
end
So I haven’t used the associations so far so I’m not sure of their purpose or maybe I’m doing things incorrectly? 
Outside of that though,
Hoped for something like “you don’t have to create this record/transaction yourself. If you do this and that, then Ecto will take care of everything” 























