Method documentation for ActiveRecord::Relation::QueryMethods#join is wrong

The documentation for this method is incorrect - the joins to the comments table would only be aliased if the table were previously joined in a different context, like User.joins(:comments, posts: :comments). It should instead read:

    # Nested joins:
    #
    #   User.joins(posts: [:comments])
    #   # SELECT "users".*
    #   # FROM "users"
    #   # INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
    #   # INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"

I coincidentally found this while trying to find some way to “ask” a AR relation what join aliases are currently being used and how I can tie those back to the joins in my query. Using a similar example:

# Joining the posts table twice causes the second join to be aliased with "posts_comments".
puts User(:posts, comments: :post).to_sql
=> SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" INNER JOIN "comments" ON "comments"."user_id" = "users"."id" INNER JOIN "posts" "posts_comments" ON "posts_comments"."id" = "comments"."post_id"

# Filtering on the first join is easy, filtering on the second join is not, notice below that "posts" table is incorrectly referenced twice:
puts User.joins(:posts, comments: :post).where(posts: { title: "dogs" }, comments: { posts: { title: "dogs" } }).to_sql
=> SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" INNER JOIN "comments" ON "comments"."user_id" = "users"."id" INNER JOIN "posts" "posts_comments" ON "posts_comments"."id" = "comments"."post_id" WHERE "posts"."title" = 'dogs' AND "posts"."title" = 'dogs'

I see that a relation has an alias_tracker method that you can call aliases on, but it would be very handy to be able to do the following (I would open a PR for this myself, but the documentation for building joins is all undocumented and confusing to me):

relation = User.joins(:posts, comments: :post)
alias = relation.join_alias_for(comments: :post)
relation.where(alias => { title: "foo" }) # correctly uses posts_comments table alias
2 Likes

I have opened Docs: ActiveRecord::QueryMethods#joins Fixes SQL output by PhilCoggins · Pull Request #39840 · rails/rails · GitHub to correct the API documentation.

Still interested to hear any thoughts on tracking / checking table aliases used in a given relation.