hyperstack-org / hyperstack-org/hyperstack
hyper-model incorrectly loads/instantiates through association
- Dominant language
- JavaScript
- Stars
- 538
- Forks
- 41
- PR merge metrics
- No merged PRs in 30d
Description
When a (kind of) complex through association is present, and you call the association without the through records loaded, hyper-model will incorrectly load them
```ruby
class User < ApplicationRecord
has_many :organization_memberships,
dependent: :destroy,
inverse_of: :user
has_many :organizations,
class_name: 'Organization',
inverse_of: :members,
source: :organization,
through: :organization_memberships
end
class Organization < ApplicationRecord
has_many :memberships,
-> { includes(:user).order('users.nickname ASC').references(:user) },
class_name: 'OrganizationMembership',
dependent: :destroy,
inverse_of: :organization
has_many :members,
-> { order('users.nickname ASC') },
class_name: 'User',
inverse_of: :organizations,
source: :user,
through: :memberships
end
class OrganizationMembership < ApplicationRecord
belongs_to :organization, inverse_of: :memberships
belongs_to :user, inverse_of: :organization_memberships
end
```
And then requesting any data from an organization through user will cause it to improperly instantiate the through association, causing the inverse the be totally busted
```ruby
render do
User.first.organizations.each do |organization|
organization.name
end
end
```
Will cause this to happen
```ruby
Organization.first.members.target_klass
# => Organization
```
It should be User. And while the association still kind of works, it breaks when you try to do any sort of scoping on that association.
The problem happens when it sets up the through association, it mistakenly sets both the owner and target_klass to Organization.
This is the code where I found the problem:
```ruby
module ActiveRecord
module Associations
class AssociationReflection
def add_member(member, owner)
owner.attributes[attribute] ||= ReactiveRecord::Collection.new(owner_class, owner, self)
owner.attributes[attribute]._internal_push member
end
end
end
end
```
I'm not sure if the association reflection set up is just already busted, but changing owner_class to member.class seems to fix the issue
```ruby
module ActiveRecord
module Associations
class AssociationReflection
def add_member(member, owner)
owner.attributes[attribute] ||= ReactiveRecord::Collection.new(member.class, owner, self)
owner.attributes[attribute]._internal_push member
end
end
end
end
```
The other interesting thing, is if you call the association the other way around `Organization.first.members` it seems to properly set things up first, and then it is never broken.
Contributor guide
Assessment
This issue has not been assessed yet.