-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add preload_order for has_one #4505
base: master
Are you sure you want to change the base?
feat: add preload_order for has_one #4505
Conversation
b1164b0
to
b116bd7
Compare
Hi @saveman71 , Regarding the example you gave, what do you mean by the request failed? Basically I'm not sure I understand what was your original reason for adding the filter |
To be sure, I was talking about the business request entity, not Ecto's request :) I amended my first message to make it more explicit Regarding my example: A request can have 3 states, created/failed/signed basically we want to display them by order of importance : created > signed > failed so the previous developer, having no other option filtered them by This was acceptable to just never display the failed requests, but a better approach is to consider the latest The |
The big question is why do you need it to be an association? If you only need to query data, it is better to write a regular query, and not pollute fields in the parent struct with associations. I would only recommend associations when they are an essential part of your schema (you always access/preload them) or when you want to both read and write (via changesets) to them. Using associations as query helpers is definitely an anti-pattern. |
We indeed never write to this assoc, if this is what you mean. In that case well... we definitely overuse this pattern. Wasn't the I don't think we're the only ones doing this out there EDIT: when rendering this document, it's also helpful to be able to access the signing request via |
You can use |
One thing that is nice with associations is you get the parallel preload for free. I could see that as a reason to use it for querying only. But in this case I actually am hesitant about the idea of adding We recently added support to preload subqueries. You could probably make a subquery with what you want and preload that . |
Could you please point me to the documentation? Is it at the schema level, or when you give the preload options to a query? We've been doing the later for some time (on other schemas), but it would be nice to have some defaults. @josevalim you're right that the use case is debatable. It also questions what happens if you edit that assoc, it would update the "ordered one" which if I'm playing the devil's advocate is better than to edit the random entry you got since it doens't ensure that there's only 1 matched record. We'll also discuss internally what we like best, if we go the other way (manual query), we won't need this, however, when looking around I can find other discussions linked to that "situation": https://elixirforum.com/t/ecto-has-one-sort-association/62923 (linked if first post) |
I think we didn't update the documentation, apologies. But you should be able to do something like this squery = from c in Comment, where: c.post_id == parent_as(:post).id, c.order_by: [desc: :id], limit: 1
from p in Post, as: :post, lateral_join: s in subquery(squery), on: true, preload: [one_comment: s] Where edit: Or perhaps you can have a regular |
I would very much like this to go into production, I don't understand what is so bad about this structure comparing to the has_many. |
Hello there,
Stumbling on https://elixirforum.com/t/ecto-has-one-sort-association/62923 earlier this afternoon and after considering what adding support for
preload_order
to thehas_one
assoc would entail, I gave it a shot.I know this is probably a solution to a bad architecture, but it could save us the trouble of converting our assoc to an
has_many
then adding a limit and/or always considering getting the latest object in business logic.A brief explanation on why we need this:
We have
Document
sDocuments
can be signed and thus someSigningRequest
s are attachedOnly one request is active at any time, we will never show multiple requests in the UI
However, some can fail, etc.
Up until recently we had the following:
Which worked but it hid any failed
SigningRequest
.When noticing this, I didn't thing too much about it and removed the filter. However, since the sort is undefined, in some cases if you have a failed signature and a successful one, it returns the first found, the failed one.
To fix this, with
preload_order
support we could do:(or on inserted_at, etc.) which would ensure that we always return the latest one, regardless of it's status (if a user chose to overwrite a successful signature, why not)
This PR is meant as an RFC, and the new
case
is not pretty (its here to avoidEcto.Association.BelongsTo
which doesn't havepreload_order
). Documentation would follow if accepted.Made a quick tests and it seems to work for our use case
Cheers!