Ensure custom PK types are casted in through reflection queries#36847
Ensure custom PK types are casted in through reflection queries#36847gmcgibbon merged 1 commit intorails:masterfrom
Conversation
07f918e to
530e382
Compare
Make sure primary keys with non-integer types can be correctly type casted in through reflections.
530e382 to
5ec2f35
Compare
|
This breaks ActiveStorage associations for UUID primary keys. It also breaks has_many with the through option with UUID primary keys. This correctly worked in 5.2.3, and all of the intermediate classes correctly define their associations. So this seems like a regression. |
|
@ekampp Can you open an issue and reproduce the problem in the bug report template? Thanks! |
|
I guess I can, but wouldn't it be better to have some more thorough tests rather than everybody having to open individual bug reports on every ID type? |
|
I see this in the code for this PR: This will always trigger the NotImplementedError for anything other than integers, right? |
That isn't really the point. I want to see why this change is causing you trouble first before we try and fix anything. Also, we can only guess at how to solve a problem without reproduction steps.
If you don't have the correct associations in place to properly type cast IDs, yes. Please read the issue this PR fixes for context. |
I don't actually see any tests in this PR for any PK types other than integers? So how are you even sure that your PR correctly handles anything other than Integers? This is a fairly complex guard for you to be that confident that you're not accidentally breaking non-integer PK types. |
|
In any case. Here is the demo project that illustrates the problem. |
|
The error message I'm getting is:
But the account doesn't have a single project association and nor should it have a single one. It has multiple project associations which is entirely correct and by design. So the error message seems to also be incorrect. |
|
This is still a problem with # Table name: documents
#
# id :uuid not null, primary key
class Document < ApplicationRecord
has_many :sections
has_many :paragraphs, through: :sections
end
# Table name: sections
#
# id :uuid not null, primary key
# document_id :uuid
class Section < ApplicationRecord
belongs_to :document
has_many :paragraphs
end
# Table name: paragraphs
# id :uuid not null, primary key
# section_id :uuid not null
class Paragraph < ApplicationRecord
belongs_to :section
endirb(main)> document.paragraphs
Traceback (most recent call last):
1: from (irb):5
NotImplementedError (In order to correctly type cast Document.id, Payment needs to define a :sections association.) |
|
Not just |
|
I added a test script to reproduce this error in #38340 (comment) |
| @klass ||= delegate_reflection.compute_class(class_name).tap do |klass| | ||
| if !parent_reflection.is_a?(HasAndBelongsToManyReflection) && | ||
| !klass.reflections.include?(options[:through].to_s) && | ||
| active_record.type_for_attribute(active_record.primary_key).type != :integer |
There was a problem hiding this comment.
re: #38340 I updated this line to be:
![:integer, :uuid].include?(active_record.type_for_attribute(active_record.primary_key).type)
This "Works For Me" in the sense that it allows my hacking around with the new ActiveStorage proxy feature to continue.
Summary
Make sure primary keys with non-integer types (eg. binary) can be correctly type casted in queries using through reflections.
Fixes #35839.
I deferred this check to happen when the through reflection computes its class and memoizes the result. Still, I'm curious if this one time runtime check is too expensive. Thoughts?