Yeah, but without knowing the implementation reasons, I don’t really find this intuitive and comfortable. I would have expected to be able to use it like the insert function.
The reason for this is that it’s supposed to be a bit lower level than Repo.insert, so that it accepts table names as the first argument, Repo.insert_all("users", [...]). And it doesn’t need schemas to be defined, you just pass the maps with some data. That’s why it doesn’t know that it needs to add a inserted_at timestamp.
It looks like only lists of maps or keyword lists are supported. From the @spec:
entries :: [map | Keyword.t]
There is some explanation in the documentation about why this is the case:
However any other autogenerated value, like timestamps, won’t be autogenerated when using insert_all/3. This is by design as this function aims to be a more direct way to insert data into the database without the conveniences of insert/2. This is also consistent with update_all/3 that does not handle timestamps as well.
It is also not possible to use insert_all to insert across multiple tables, therefore associations are not supported.
It does feel like a shortcoming though, I’m not sure why it doesn’t work with schemas/structs.
EDIT: You could create a utility around Multi like this:
def insert_multiple(entries) do
multi =
Enum.reduce entries, Multi.new(), fn(multi, entry) ->
Multi.insert(multi, entry.id, entry)
end
Repo.transaction(multi)
end
It depends on the struct to have an id field for the multi name, but you could change that to anything I think, it just needs to be unique.