ex_machina
ex_machina copied to clipboard
Confusing example in docs
The Overview section shows example of Article
factory:
def article_factory do
%MyApp.Article{
title: "Use ExMachina!",
# associations are inserted when you call `insert`
author: build(:user),
}
end
However, in Ecto Associations section there is following snippet:
def article_factory do
%Article{
title: "Use ExMachina!",
# associations are inserted when you call `insert`
comments: [build(:comment)],
author: build(:user),
}
end
Since Article
has many Comments
, please clarify how the two forms differ from each other. It will surely help newcomers to understand ExMachina basic concepts.
@onegrx I'm not sure I understand the confusion. They are both the same form. If you have an association you can set it. If it's a has_many
then you need to put it in a list first.
Is it confusing that the example aren't exactly the same in both sections?
It's confusing for me when and where I have to put associations. For example I have something like this:
def parent_params_factory do
%{
unique_name: "John",
children: [build(:child)]
}
end
def child_params_factory do
%{
parent: build(:parent)
}
end
def parent_factory do
struct(Parent, build(:parent_params))
end
def child_factory do
struct(Child, build(:child_params))
end
Parent has_many
childern, so each child belongs_to
parent. However when I run this, I got a loop and constraint error on database. I assume that parent builds for himself a couple (how many?) children, and since each child has parent it builds a new one instead of using the one who built him. This leads to creating many parents with the same name.
I'd be extremely grateful if you could help mi with this. I titled it confusing docs because I couldn't find anything about this problem and when analysing examples I found mentioned inconsistency. It is also possible that I am misunderstanding some concepts - would you be so nice @paulcsmith to clarify it for me or even put into docs?
Thank you in advance.
I think in this case you'd want to have something like this:
def parent_factory do
build(:parent_without_children,
children: [build(:child_without_parent)])
end
def parent_without_children_factory do
%Parent{
unique_name: "John"
}
end
def child_factory do
build(:child_without_parent,
parent: build(:parent_without_children))
end
def child_without_parent_factory do
%Child{}
end
This would allow you to use both the parent and the child factory as the building point and both would be consistent.
insert(:parent) # has a child
insert(:child) # has a parent
The "loop" is created because ExMachina builds the fields eagerly.
If you didn't plan on using either the child or the parent factory, you could leave out the association on that factory to avoid having to define those helper factories just like the first example in the docs.