Skip to content

Commit d775da3

Browse files
committed
Keep the :fallback null object out of relation serialization
serializable_hash serializes included associations through serialize_relations, which read the association with a bare send(name) outside the without_autobuild block that already wraps field serialization. With a :fallback that returned the null object, and serializable_hash(include: ...) then called serializable_hash on it, raising NoMethodError. When the association has a :fallback, read the value through without_autobuild so a nil association is omitted from the output. Autobuilding associations are left untouched.
1 parent e1cb615 commit d775da3

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

lib/mongoid/serializable.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,18 @@ def serialize_relations(attributes = {}, options = {})
127127
inclusions = options[:include]
128128
relation_names(inclusions).each do |name|
129129
association = relations[name.to_s]
130-
if association && relation = send(association.name)
131-
attributes[association.name.to_s] =
132-
relation.serializable_hash(relation_options(inclusions, options, name))
133-
end
130+
next unless association
131+
132+
relation =
133+
if association.fallback?
134+
without_autobuild { send(association.name) }
135+
else
136+
send(association.name)
137+
end
138+
next unless relation
139+
140+
attributes[association.name.to_s] =
141+
relation.serializable_hash(relation_options(inclusions, options, name))
134142
end
135143
end
136144

spec/mongoid/association/fallback_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,32 @@ class Symphony
352352
end
353353
end
354354

355+
context 'when serialized with an included association' do
356+
before(:all) do
357+
class Composer
358+
include Mongoid::Document
359+
end
360+
361+
class Symphony
362+
include Mongoid::Document
363+
364+
belongs_to :composer, fallback: -> { Anonymous.new }
365+
end
366+
end
367+
368+
after(:all) do
369+
Object.send(:remove_const, :Symphony)
370+
Object.send(:remove_const, :Composer)
371+
end
372+
373+
it 'omits the fallback when the real association is nil' do
374+
symphony = Symphony.new
375+
376+
expect { symphony.serializable_hash(include: :composer) }.not_to raise_error
377+
expect(symphony.serializable_hash(include: :composer)).not_to have_key('composer')
378+
end
379+
end
380+
355381
context 'validation of the :fallback option' do
356382
it 'rejects a declaration that combines :fallback with :autobuild' do
357383
expect do

0 commit comments

Comments
 (0)