Skip to content

Commit

Permalink
Add ecto_query: :preload option to preload query (#4503)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtimberlake authored Aug 27, 2024
1 parent 840eedf commit b59453f
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
4 changes: 2 additions & 2 deletions guides/howtos/Multi tenancy with foreign keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule MyApp.Repo do
@impl true
def prepare_query(_operation, query, opts) do
cond do
opts[:skip_org_id] || opts[:schema_migration] ->
opts[:skip_org_id] || opts[:ecto_query] in [:schema_migrations, :preload] ->
{query, opts}

org_id = opts[:org_id] ->
Expand All @@ -44,7 +44,7 @@ Now we can pass `:org_id` to all READ operations, such as `get`, `get_by`, `prel

* if you explicitly set `:skip_org_id` to true, it won't require an `:org_id`. This reduces the odds of a developer forgetting to scope their queries, which can accidentally expose private data to other users

* if the `:schema_migration` option is set. This means the repository operation was issued by Ecto itself when migrating our database and we don't want to apply an `org_id` to them
* if the `:ecto_query` option is set. This means the repository operation was issued by Ecto itself, with value `:schema_migration` when migrating our database, or `:preload` when issuing a preload query, and we don't want to apply an `org_id` to them

Still, setting the `org_id` for every operation is cumbersome and error prone. We will be better served if all operations attempt to set an `org_id`.

Expand Down
10 changes: 9 additions & 1 deletion lib/ecto/repo/preloader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@ defmodule Ecto.Repo.Preloader do
normalize_and_preload_each([struct], repo_name, preloads, opts[:take], %{}, tuplet) |> hd()
end

defp normalize_and_preload_each(structs, repo_name, preloads, take, query_assocs, tuplet) do
defp normalize_and_preload_each(
structs,
repo_name,
preloads,
take,
query_assocs,
{adapter_meta, opts}
) do
tuplet = {adapter_meta, Keyword.put(opts, :ecto_query, :preload)}
preloads = normalize(preloads, take, preloads)
preload_each(structs, repo_name, preloads, query_assocs, tuplet)
rescue
Expand Down
2 changes: 1 addition & 1 deletion test/ecto/repo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2162,7 +2162,7 @@ defmodule Ecto.RepoTest do

test "preload" do
PrepareRepo.preload(%MySchemaWithAssoc{parent_id: 1}, :parent, hello: :world)
assert_received {:all, query, _}
assert_received {:all, query, [ecto_query: :preload, hello: :world]}
assert query.from.source == {"my_parent", Ecto.RepoTest.MyParent}
end

Expand Down

0 comments on commit b59453f

Please sign in to comment.