Created
February 8, 2025 08:38
-
-
Save Wigny/66c83d7fa3673eabee96982a86ae9372 to your computer and use it in GitHub Desktop.
Dataloader usage example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Mix.install([:dataloader]) | |
defmodule User do | |
defstruct [:id, :name] | |
def list do | |
[ | |
%__MODULE__{id: 1, name: "John"}, | |
%__MODULE__{id: 2, name: "Alice"}, | |
%__MODULE__{id: 3, name: "Bob"} | |
] | |
end | |
end | |
defmodule Post do | |
defstruct [:id, :user_id, :content] | |
def first, do: List.first(list()) | |
def list do | |
[ | |
%__MODULE__{id: 1, user_id: 1, content: "..."}, | |
%__MODULE__{id: 2, user_id: 2, content: "..."}, | |
%__MODULE__{id: 3, user_id: 3, content: "..."} | |
] | |
end | |
end | |
defmodule Comment do | |
defstruct [:user_id, :post_id, :message] | |
def list(filter \\ %{}) do | |
for comment <- [ | |
%__MODULE__{post_id: 1, user_id: 2, message: "..."}, | |
%__MODULE__{post_id: 1, user_id: 2, message: "..."}, | |
%__MODULE__{post_id: 1, user_id: 3, message: "..."}, | |
%__MODULE__{post_id: 2, user_id: 1, message: "..."}, | |
%__MODULE__{post_id: 3, user_id: 2, message: "..."} | |
], | |
Map.take(comment, Map.keys(filter)) == filter, | |
do: comment | |
end | |
end | |
defmodule DataSource do | |
def new do | |
Dataloader.KV.new(&load/2) | |
end | |
defp load(:comments, posts) do | |
Map.new(posts, fn %Post{} = post -> | |
comments = Comment.list(%{post_id: post.id}) | |
{post, comments} | |
end) | |
end | |
defp load({:comments, %{user: user}}, posts) do | |
Map.new(posts, fn %Post{} = post -> | |
comments = Comment.list(%{post_id: post.id, user_id: user.id}) | |
{post, comments} | |
end) | |
end | |
defp load(:commenters, posts) do | |
Map.new(posts, fn %Post{} = post -> | |
comments = Comment.list(%{post_id: post.id}) | |
commenters_id = Enum.map(comments, & &1.user_id) | |
commenters = Enum.filter(User.list(), &(&1.id in commenters_id)) | |
{post, commenters} | |
end) | |
end | |
end | |
ExUnit.start() | |
ExUnit.run() | |
defmodule Test do | |
use ExUnit.Case, async: true | |
test "load comments post" do | |
post = Post.first() | |
loader = Dataloader.add_source(Dataloader.new(), :example, DataSource.new()) | |
loader = Dataloader.load(loader, :example, :comments, post) | |
loader = Dataloader.run(loader) | |
comments = Dataloader.get(loader, :example, :comments, post) | |
assert comments == [ | |
%Comment{post_id: post.id, user_id: 2, message: "..."}, | |
%Comment{post_id: post.id, user_id: 2, message: "..."}, | |
%Comment{post_id: post.id, user_id: 3, message: "..."} | |
] | |
end | |
test "load user comments on post" do | |
user = %User{id: 2} | |
post = Post.first() | |
loader = Dataloader.add_source(Dataloader.new(), :example, DataSource.new()) | |
loader = Dataloader.load(loader, :example, {:comments, %{user: user}}, post) | |
loader = Dataloader.run(loader) | |
comments = Dataloader.get(loader, :example, {:comments, %{user: user}}, post) | |
assert comments == [ | |
%Comment{post_id: post.id, user_id: user.id, message: "..."}, | |
%Comment{post_id: post.id, user_id: user.id, message: "..."} | |
] | |
end | |
test "load user comments on many posts" do | |
user = %User{id: 2} | |
posts = Post.list() | |
loader = Dataloader.add_source(Dataloader.new(), :example, DataSource.new()) | |
loader = Dataloader.load_many(loader, :example, {:comments, %{user: user}}, posts) | |
loader = Dataloader.run(loader) | |
posts_comments = Dataloader.get_many(loader, :example, {:comments, %{user: user}}, posts) | |
assert posts_comments == [ | |
[ | |
%Comment{post_id: 1, user_id: 2, message: "..."}, | |
%Comment{post_id: 1, user_id: 2, message: "..."} | |
], | |
[], | |
[ | |
%Comment{post_id: 3, user_id: 2, message: "..."} | |
] | |
] | |
last_post_comments = | |
Dataloader.get(loader, :example, {:comments, %{user: user}}, List.last(posts)) | |
assert last_post_comments == [ | |
%Comment{post_id: 3, user_id: 2, message: "..."} | |
] | |
end | |
test "load commenters of post" do | |
[post1, post2, post3] = Post.list() | |
loader = Dataloader.add_source(Dataloader.new(), :example, DataSource.new()) | |
loader = Dataloader.load_many(loader, :example, :commenters, [post1, post2, post3]) | |
loader = Dataloader.run(loader) | |
assert Dataloader.get(loader, :example, :commenters, post1) == [ | |
%User{id: 2, name: "Alice"}, | |
%User{id: 3, name: "Bob"} | |
] | |
assert Dataloader.get(loader, :example, :commenters, post2) == [ | |
%User{id: 1, name: "John"} | |
] | |
assert Dataloader.get(loader, :example, :commenters, post3) == [ | |
%User{id: 2, name: "Alice"} | |
] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment