Skip to content

Commit 5de9346

Browse files
authored
MONGOID-5344 Using concat on has_and_belongs_to_many ids default value is not working the first time (#5268)
* MONGOID-5344 Using concat on has_and_belongs_to_many ids default value is not working the first time * MONGOID-5344 add has_many test
1 parent 89fa3f9 commit 5de9346

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

lib/mongoid/document.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def instantiate(attrs = nil, selected_fields = nil, &block)
309309
#
310310
# @api private
311311
def instantiate_document(attrs = nil, selected_fields = nil, execute_callbacks: true)
312-
attributes = attrs || {}
312+
attributes = attrs&.to_h || {}
313313
doc = allocate
314314
doc.__selected_fields = selected_fields
315315
doc.instance_variable_set(:@attributes, attributes)

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3796,4 +3796,31 @@ class Distributor
37963796
expect(Breed.aliased_associations["dog_ids"]).to eq("dogs")
37973797
end
37983798
end
3799+
3800+
# This test is for MONGOID-5344 which tests that the initial call to
3801+
# signature_ids refers to the same array as subsequent calls to signature_ids.
3802+
# Prior to the change in that ticket, this test broke because the array
3803+
# returned from write_attribute (which is triggered the first time the
3804+
# foreign key array is referenced, to set the default), refers to a different
3805+
# array to the one stored in the attributes hash. This happened because,
3806+
# when retrieving a document from the database, the attributes hash is actually
3807+
# a BSON::Document, which applies a transformation to the array before
3808+
# storing it.
3809+
context "when executing concat on foreign key array from the db" do
3810+
before do
3811+
HabtmmContract.create!
3812+
HabtmmSignature.create!
3813+
end
3814+
3815+
let!(:contract) { HabtmmContract.first }
3816+
let!(:signature) { HabtmmSignature.first }
3817+
3818+
before do
3819+
contract.signature_ids.concat([signature.id])
3820+
end
3821+
3822+
it "works on the first attempt" do
3823+
expect(contract.signature_ids).to eq([signature.id])
3824+
end
3825+
end
37993826
end

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4122,4 +4122,22 @@
41224122
expect(Artist.aliased_fields["band"]).to eq("band_id")
41234123
end
41244124
end
4125+
4126+
context "when executing concat on foreign key array from the db" do
4127+
before do
4128+
Agent.create!
4129+
Basic.create!
4130+
end
4131+
4132+
let!(:agent) { Agent.first }
4133+
let!(:basic) { Basic.first }
4134+
4135+
before do
4136+
agent.basic_ids.concat([basic.id])
4137+
end
4138+
4139+
it "works on the first attempt" do
4140+
expect(agent.basic_ids).to eq([basic.id])
4141+
end
4142+
end
41254143
end

spec/mongoid/attributes_spec.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,49 @@
16761676
end
16771677
end
16781678
end
1679+
1680+
context "when comparing the object_ids of the written value" do
1681+
1682+
before do
1683+
Person.create!
1684+
end
1685+
1686+
let(:person) do
1687+
Person.first
1688+
end
1689+
1690+
context "when the field is not resizable" do
1691+
let(:test) do
1692+
person.write_attribute(:test, "aliased field to test")
1693+
end
1694+
1695+
it "has the same object_id as the attributes hash value" do
1696+
expect(test.object_id).to eq(person.test.object_id)
1697+
end
1698+
end
1699+
1700+
context "when the field is resizable" do
1701+
1702+
let(:arrays) do
1703+
person.write_attribute(:arrays, [])
1704+
end
1705+
1706+
it "has the same object_id as the attributes hash value" do
1707+
expect(arrays.object_id).to eq(person.arrays.object_id)
1708+
end
1709+
end
1710+
1711+
context "when the field is a HABTM foreign key array" do
1712+
1713+
let(:preference_ids) do
1714+
person.write_attribute(:preference_ids, [])
1715+
end
1716+
1717+
it "has the same object_id as the attributes hash value" do
1718+
expect(preference_ids.object_id).to eq(person.preference_ids.object_id)
1719+
end
1720+
end
1721+
end
16791722
end
16801723

16811724
describe "#typed_value_for" do

0 commit comments

Comments
 (0)