luckyframework / luckyframework/avram

has_many through does not use association primary key type

Open
#249 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Crystal
Stars
183
Forks
67
PR merge metrics
No merged PRs in 30d

Description

If one side of a `has_many` through is using a custom primary key type the macro generated code does not compile.

For example:

* I have a `Category` with an `Int16` primary key
* `Post` with `Int64` primary key
* Join table `PostCategories` with `Int16` `category_id` and `Int64` `post_id`

Simplified versions of the models look like this:

```crystal
class Post < BaseModel
table do
column title : String
has_many post_categories : PostCategory
has_many categories : Category, through: :post_categories
end
end

class Category < BaseModel
skip_default_columns

table do
primary_key id : Int16
column name : String
has_many post_categories : PostCategory
has_many posts : Post, through: :post_categories
end
end

class PostCategory < BaseModel
skip_default_columns

table do
primary_key id : Int64
belongs_to post : Post
belongs_to category : Category
end
end
```

I'm getting the error:

```
There was a problem expanding macro 'define_has_many_base_query'

Code in macro 'has_many'

20 | define_has_many_base_query(posts, Post, category_id, :post_categories)
^
Called macro defined in lib/avram/src/avram/associations/has_many.cr:27:11

27 | private macro define_has_many_base_query(assoc_name, model, foreign_key, through)

Which expanded to:

> 20 | all_posts.each do |item|
> 21 | item.post_categories.each do |item_through|
> 22 | posts[item_through.category_id] ||= Array(Post).new
^-
Error: no overload matches 'Hash(Int64, Array(Post))#[]=' with types Int16, Array(Post)

Overloads are:
- Hash(K, V)#[]=(key : K, value : V)
```

In

https://github.com/luckyframework/avram/blob/0a20d2a035751cc63831a6d7d547b56f124ff221/src/avram/associations/has_many.cr#L46

It's expanding to `{} of Post::PrimaryKeyType => Array(Post)` and then attempting to use an `Int16` as the key in that Hash: (`posts[item_through.category_id] ||= Array(Post).new`)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at src/avram/associations/has_many.cr around line 46 and inspect the generated through-association query and its hash key type. Reproduce the issue with the Int16 Category and Int64 Post models from the report; done means the generated code compiles and handles the mixed primary-key types.

Written by the indexing model from the issue text.

Assessment

Tech stack
crystal
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.