Skip to content

Commit 38370cd

Browse files
authored
Fix MONGOID-5089 HABTM inconsistencies (#5224)
* MONGOID-4953 fix MONGOID-5089 HABTM inconsistencies * MONGOID-5089 add testing for aliased associations * MONGOID-5089 document the aliased_associations attribute
1 parent f3ff024 commit 38370cd

File tree

6 files changed

+52
-1
lines changed

6 files changed

+52
-1
lines changed

lib/mongoid/association/macros.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,28 @@ module Macros
1212
class_attribute :embedded, instance_reader: false
1313
class_attribute :embedded_relations
1414
class_attribute :relations
15+
16+
# A hash that maps aliases to their associations. This is used when
17+
# associations specify the `as` option, or on a referenced association.
18+
# On a referenced association, this is used to map the foreign key to
19+
# the association's name. For example, if we had the following
20+
# relationship:
21+
#
22+
# User has_many Accounts
23+
#
24+
# User will have an entry in the aliased associations hash:
25+
#
26+
# account_ids => accounts
27+
#
28+
# Note that on the belongs_to associations, the mapping from
29+
# foreign key => name is not in the aliased_associations hash, but a
30+
# mapping from name => foreign key is in the aliased_fields hash.
31+
#
32+
# @return [ Hash<String, String> ] The aliased associations hash.
33+
#
1534
# @api private
1635
class_attribute :aliased_associations
36+
1737
self.embedded = false
1838
self.embedded_relations = BSON::Document.new
1939
self.relations = BSON::Document.new

lib/mongoid/association/referenced/has_and_belongs_to_many.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def synced_save
230230
end
231231

232232
def create_foreign_key_field!
233+
inverse_class.aliased_associations[foreign_key] = name.to_s
233234
@owner_class.field(
234235
foreign_key,
235236
type: FOREIGN_KEY_FIELD_TYPE,

lib/mongoid/attributes/processing.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ def process_attributes(attrs = nil)
4343
# @return [ true, false ] True if pending, false if not.
4444
def pending_attribute?(key, value)
4545
name = key.to_s
46-
aliased = aliased_associations[name] if aliased_associations.key?(name)
46+
47+
aliased = if aliased_associations.key?(name)
48+
aliased_associations[name]
49+
else
50+
name
51+
end
52+
4753
if relations.has_key?(aliased)
4854
pending_relations[name] = value
4955
return true

spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,4 +3789,11 @@ class Distributor
37893789
expect(signature.contracts.first.signature_ids).to eq([signature.id])
37903790
end
37913791
end
3792+
3793+
context "when there is a foreign key in the aliased associations" do
3794+
it "has the correct aliases" do
3795+
expect(Dog.aliased_associations["breed_ids"]).to eq("breeds")
3796+
expect(Breed.aliased_associations["dog_ids"]).to eq("dogs")
3797+
end
3798+
end
37923799
end

spec/mongoid/association/referenced/has_many/proxy_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,4 +4114,12 @@
41144114
expect(person2.posts_count).to eq 0
41154115
end
41164116
end
4117+
4118+
context "when there is a foreign key in the aliased associations" do
4119+
it "has the correct aliases" do
4120+
expect(Band.aliased_associations["artist_ids"]).to eq("artists")
4121+
expect(Artist.aliased_associations.key?("band_id")).to be false
4122+
expect(Artist.aliased_fields["band"]).to eq("band_id")
4123+
end
4124+
end
41174125
end

spec/mongoid/association/referenced/has_one/proxy_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,4 +1139,13 @@
11391139
end
11401140
end
11411141
end
1142+
1143+
context "when there is a foreign key in the aliased associations" do
1144+
it "has the correct aliases" do
1145+
# Instances of Driver do not respond to vehicle_id.
1146+
expect(Driver.aliased_associations.key?("vehicle_id")).to be false
1147+
expect(Vehicle.aliased_associations.key?("driver_id")).to be false
1148+
expect(Vehicle.aliased_fields["driver"]).to eq("driver_id")
1149+
end
1150+
end
11421151
end

0 commit comments

Comments
 (0)