This is really fast question only for my information if it is normal, or for getting some tip how to avoid if its really bad move.
I write tests for my Book API and while testing get_book/list_books etc. Assert fails because my goal was’nt to preload user while fetching Book from db. It fetches whole informations about associated user. I think user_id is enough to get for example his email, or put link to a book creator account.
I post whole road to create and get book and then my test.
Controller
def create(conn, %{"book" => book_params}) do
user = conn.assigns.current_user
with {:ok, %Book{} = _book} <- Books.create_book(user, book_params) do
conn
|> put_status(:created)
|> json(%{message: "created"})
end
end
Context
def create_book(user, %{"authors" => _authors, "categories" => _categories} = attrs) do
%Book{}
|> Book.changeset(Map.drop(attrs, ["authors", "categories"]))
|> Ecto.Changeset.put_assoc(:user, user)
|> load_authors_assoc(attrs)
|> load_categories_assoc(attrs)
|> Repo.insert()
end
Context get_book/1
def get_book(id), do: Repo.get(Book, id) |> Repo.preload([:authors, :categories])
Test
@valid_attrs %{
"title" => "Book 1",
"description" => "Book description",
"isbn" => "111-111-111",
"published" => 2000,
"authors" => "author",
"categories" => "category"
}
setup do
%{user: AccountsFixtures.user_fixture()}
end
test "get_book/1 returns the book with given id", %{user: user} do
book = BooksFixtures.book_fixture(user, @valid_attrs)
assert Books.get_book(book.id) == book
end
Test fails because left side dont load the user info, just his id. Right side basically show whole user what I think is not too good.
user: #Ecto.Association.NotLoaded<association :user is not loaded>,
Versus:
user: %Bookshare.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, email: "user-576460752303423165@example.com", hash_password: "$2b$04$oyDM7WvxEIOTprM2Gb/f8uobuAeFKYbxwxST8I50iMR8vmjFRLsoe", id: 2240, inserted_at: ~N[2022-11-13 19:47:36], is_confirmed: false, password: nil, profile: #Ecto.Association.NotLoaded<association :profile is not loaded>, updated_at: ~N[2022-11-13 19:47:36]},
I know that to pass test I have to change get_book function to:
def get_book(id), do: Repo.get(Book, id) |> Repo.preload([:user, :authors, :categories])
But I would like to know if I can avoid fetching user data. I suppose it happens because I put into create_book function current user and then make association in changeset. Maybe instead of putting user to function I should put just user_id which contains enought information about owner and not too much for viewers.
The only thing about relationship written in book.ex and user.ex is
belongs_to :user, Bookshare.Accounts.User, foreign_key: :user_id