ex_machina
ex_machina copied to clipboard
Naively inserting a record with children doesn't work
First, thanks for the awesome project!
I'm working on an app that has two Ecto schemas, Order and Product. Orders have many products, and products belong to orders. I have the following factories:
def order_factory() do
%MyApp.Order{
# snip
}
end
def product_factory() do
%MyApp.Product{
# snip
order: build(:order),
}
end
In my tests I attempt to insert an order and a list of products like so:
order = insert(:order, products: [build(:product)])
and I get the somewhat cryptic error "** (ArgumentError) cannot change belongs_to association order because there is already a change setting its foreign key order_id to 3305".
This works, though:
order = insert(:order, products: [build(:product, order: nil)])
It's not a terribly difficult workaround, but it adds a significant amount of irrelevant noise to my tests, especially on tests which require deeply nested objects.
Thank you @bencates for posting this workaround! My current solution was to insert order first and then product which was even more noisy. It would be great if inserting list in has_many association worked out of the box. If I have some time this week, I'll try to familiarize with ex_machina internals and check how much time it would get me to fix the issue.
Hi! I don't have full solution yet, but I have found a way to reproduce the problem.
ex_machina has a test for has_many association here:
https://github.com/thoughtbot/ex_machina/blob/master/test/ex_machina/ecto_strategy_test.exs#L55
but it passes only by accident.
In model definitions:
schema "users" do
...
has_many :articles, ExMachina.Article,
...
end
and:
schema "articles" do
...
belongs_to :author, ExMachina.User
...
end
has_many association will search user_id in Article, but Article defines author_id, so in the test when we do:
built_article = TestFactory.build(:article, visits: 10)
model = TestFactory.insert(:user, articles: [built_article])
there are actually two users created instead of one. If we fix the schema by referencing correct foreign key:
schema "users" do
...
has_many :articles, ExMachina.Article, foreign_key: :author_id,
...
end
we will get the same error as @bencates posted above. I've made clone with branch that demonstrates the problem (two tests don't pass after fixing the schema), but I don't think it makes sense to turn it into a PR before I have a fix. https://github.com/tomekowal/ex_machina/tree/fix-user-has-many-posts-association
I've submitted a PR that fixes both tests and implementation. I hope it proves useful :)