Is there any way to build the bindings and expression for Ecto.Query.preload/2
dynamically?
I am currently using joins to construct my query similar to this:
def preload(queryable, parent_id) do
queryable
|> join(
:left,
[{^parent_id, parent}],
parameter_list in assoc(parent, :parameter_list_history),
on:
parameter_list.active == true and
parameter_list.revision <= parent.parameter_list_revision,
as: :inventory_parameterlist_history
)
end
parent_id
is provided by the recursive function that composes the query for my associations.
The reason I am using joins and not just letting Ecto handle the preload is that I need to filter the associations based on a value parameter_list_revision
from a parent up in the hierarchy of associations.
This approach works very well to compose the query and it results in something like this:
from d0 in ConfigAdmin.Config.Plant.Draft,
as: :draft,
left_join: d1 in assoc(d0, :devices),
as: :config_device_draft,
on: d1.active == true,
left_join: p2 in assoc(d1, :parameter_list_history),
as: :inventory_parameterlist_history,
on: p2.active == true and p2.revision <= d1.parameter_list_revision
My problem arises when I need to call the Ecto.Query.preload/2
function.
This function appears to require the bindings and expression to be defined before compile-time.
In my code I have this now just to test that the rest works as expected:
queryable
|>Ecto.Query.preload([config_device_draft: cdd, inventory_parameterlist_history: iph], [
{:devices,
{cdd, [{:parameter_list_history, iph}]}}
])
I would like to generate the code above somehow based on my association hierarchy.
I have investigated using macros to do this but I cant seem to grasp the concept good enough…
Any suggestions on how this could be done?
Or if its possible at all, or if there would be a smarter way of doing this?
Thank you,
Morten Lund