Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib/mongoid/association/embedded/embeds_many/proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,12 @@ def as_attributes
# @api private
def update_attributes_hash
if _target.empty?
_base.attributes.delete(_association.store_as)
# Only remove the key if it is absent or nil. If it is already
# an empty array, the caller explicitly set it to [] (e.g. via
# a raw write_attribute call), and that intent must be preserved
# so the empty array is persisted to the database.
stored = _association.store_as
_base.attributes.delete(stored) unless _base.attributes[stored] == []
else
Comment thread
jamis marked this conversation as resolved.
_base.attributes.merge!(_association.store_as => _target.map(&:attributes))
end
Expand Down
33 changes: 33 additions & 0 deletions spec/mongoid/association/embedded/embeds_many/proxy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,39 @@ class DNS::Record
expect(reloaded_band).not_to have_key(:labels)
end
end

context 'when set via raw attribute write in a before_save callback' do
after { Band.reset_callbacks(:save) }

let(:reloaded_band) { Band.collection.find(_id: band._id).first }

context 'on a new record' do
before { Band.before_save { self[:labels] ||= [] } }

let(:band) { Band.create! }

it 'persists the empty list' do
expect(reloaded_band).to have_key(:labels)
expect(reloaded_band[:labels]).to eq []
end
end

context 'on an existing record' do
# Reload the band from MongoDB so the labels proxy has not been
# initialized, which is the scenario that triggers the bug.
let(:band) { Band.find(Band.create!._id) }

before do
Band.before_save { self[:labels] ||= [] }
band.save!
end

it 'persists the empty list' do
expect(reloaded_band).to have_key(:labels)
expect(reloaded_band[:labels]).to eq []
end
end
end
end

context 'when using assign_attributes with an already populated array' do
Expand Down
Loading