Thanks, that’s actually a big help for the list functions. I can actually get away without the protocol now.
Do you have any idea how to do the same for build_assoc with a many to many association without resorting to a protocol? When I call build_assoc, it only builds a blank post record. I end up having to add the record in the initiative_posts join table manually using insert_all in an Ecto.Multi transaction.
Below is what I have for the Feeds context now. Way more slick, so thanks for that!
defmodule Hydroplane.Feeds do
import Ecto.Query
alias Hydroplane.Repo
alias Hydroplane.Feeds.Feed
def list_feed_items(feedable), do: list_posts(feedable)
def list_posts(feedable) do
Ecto.assoc(feedable, :posts)
|> order_by_date()
|> Repo.all()
|> Repo.preload(:author)
end
def list_polls(feedable) do
Ecto.assoc(feedable, :polls)
|> order_by_date()
|> Repo.all()
|> Repo.preload(:author)
end
def create_post(feedable, author, attrs) do
case Feed.create_post(feedable, author, attrs) do
{:ok, %{post: post}} -> {:ok, post}
_ -> {:error, "Could not create post"}
end
end
defp order_by_date(query) do
from p in query, order_by: [desc: p.inserted_at]
end
end
Below is the protocol implementation for Initiative, which I’m not a fan of. I’d much rather be able to automatically create the record in the join table when I insert the post.
defimpl Hydroplane.Feeds.Feed, for: Hydroplane.Initiatives.Initiative do
alias Ecto.Multi
alias Hydroplane.Feeds.Post
alias Hydroplane.Repo
def create_post(initiative, author, attrs) do
Multi.new()
|> Multi.insert(:post, Post.changeset(%Post{author: author}, attrs))
|> Multi.run(:initiative_post, fn _repo, %{post: post} ->
insert_post_join(initiative, post)
end)
|> Repo.transaction()
end
defp insert_post_join(initiative, post) do
case Repo.insert_all("initiative_posts", [%{initiative_id: initiative.id, post_id: post.id}]) do
{1, _} -> {:ok, "Associated post with initiative"}
_ -> {:error, "Unable to associate post with initiative"}
end
end
end
Is there any way that I can dynamically build a changeset that inserts two records, one in post and one in the join table the many-to-many association uses?


















