luckyframework / luckyframework/avram
Has many through a has many through is broken
Nobody has claimed this yet.
- Dominant language
- Crystal
- Stars
- 183
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
This is probably more of an edge case, but if you need a model to associate to another one but through 2 layers of joins, you'll end up with something like this:
Let's say the app is a multi-tenant blog app where a user can post on many different blogs, and each of these posts have comments, so the User has many comments but through the posts that are through the blos
```crystal
table :users do
has_many blogs : Blog
has_many posts : Post, through: :blogs
has_many comments : Comment, through: :posts
end
```
When you try to use `user.comments`, you'll get an error that says:
> undefined method 'user_id' for Post::BaseQuery
The error would be correct because `posts` doesn't have `user_id`, but `blogs` does. The proper SQL for this would be:
```SQL
SELECT *
FROM users
INNER JOIN blogs ON users.id = blogs.user_id
INNER JOIN posts ON blogs.id = posts.blog_id
INNER JOIN comments ON posts.id = comments.post_id
```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the nested association example with User, Blog, Post, and Comment, then inspect the query handling behind user.comments. Compare the generated joins with the SQL shown in the issue. Done means a has-many-through association traversing two join layers resolves without the user_id error and produces the expected joins.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- crystal
- Domain
- database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100