Modelling correctness · rule direct-join-to-source
dbt models mixing ref() and source()
A Metacenta review checks this under the rule A model does not mix refs and raw sources. Everything below applies whether or not you ever commission one.
What this rule checks
This rule flags any model that depends on both a source() and a ref() to another model. It reads the model's declared dependencies, not its SQL, so it applies whether or not the two are joined. It does not need a layered project.
Why it matters
One side has been through staging's renaming and casting, and the other has not. That is where a silent type or column-name mismatch survives review.
How to fix it
Stage raw sources before joining them to models. Stage the source first, then read the resulting model alongside the other ref().
Before:
select o.order_id, p.amount
from {{ ref('stg_shop__orders') }} as o
join {{ source('stripe', 'payments') }} as p
on p.orderid = o.order_id
After:
select o.order_id, p.amount
from {{ ref('stg_shop__orders') }} as o
join {{ ref('stg_stripe__payments') }} as p
on p.order_id = o.order_id
When it is fine to leave
A small, static source such as a currency list, already clean at load, can be read directly beside a model. Describe the reason on the model. A staging model over it costs little, though, and ends the question.
What we need to check it
manifest.json alone. We read each model's depends_on, so the rule works in flat and layered projects alike.
Published rules it corresponds to
dbt_project_evaluator, rule fct_direct_join_to_source. Ours checks the same condition and threshold.
This means our check corresponds to their rule. It does not mean the publisher reviewed or endorses it.