Bylaw.Ecto.Query.Checks.ManualJoinInsteadOfAssoc (bylaw_ecto_query v0.1.0-alpha.1)

Copy Markdown View Source

Validates that manual joins use assoc/2 when a root association exists.

This check catches direct schema joins that spell out a relationship already declared on the query root schema.

Examples

Bad:

from(Post, as: :post)
|> join(:inner, [post: p], c in Comment,
  as: :comment,
  on: c.post_id == p.id
)

Why this is bad:

When Post defines has_many :comments, Comment, the query reimplements association metadata by hand. Future association changes can drift away from the manual join.

Better:

from(Post, as: :post)
|> join(:inner, [post: p], c in assoc(p, :comments),
  as: :comment
)

Why this is better:

Ecto uses the association metadata for keys, through joins, preloads, and future schema changes.

Notes

This check only rejects direct schema joins when the root schema declares a matching association. It ignores reverse-only associations and joins that are already written with assoc/2.

Association joins let Ecto use the association metadata for foreign keys, through joins, preloads, and future schema changes. Manual joins are only rejected when the joined source is an Ecto schema module and the root schema defines an association whose related schema matches it.

Options

  • :validate - explicit false disables the check. Defaults to true.

This check intentionally looks at associations defined on the root schema, because those are the associations that can be used as assoc(root, name) in the query. Reverse-only associations on the joined schema are ignored.

Usage

Add this module to the explicit check list passed through Bylaw.Ecto.Query. See Bylaw.Ecto.Query for the full Ecto.Repo.prepare_query/3 setup.

Summary

Functions

validate(operation, query, opts)

Implements the Bylaw.Ecto.Query.Check validation callback.