Skip to content

Commit cb9b8f3

Browse files
MONGOID-5624 Fix alias issue when store_as is different case (#5675)
* trying a fix for aliased field names * add a test case for bug * remove to_s * Remove _ids aliases * Revert "Remove _ids aliases" This reverts commit 24b9e67. * Add stored_as_associations * Cleanup * Fix code review remarks --------- Co-authored-by: Dmitry Rybakov <[email protected]>
1 parent be61226 commit cb9b8f3

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
lines changed

lib/mongoid/association/macros.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,15 @@ module Macros
3535
# @api private
3636
class_attribute :aliased_associations
3737

38+
# @return [ Set<String> ] The set of associations that are configured
39+
# with :store_as parameter.
40+
class_attribute :stored_as_associations
41+
3842
self.embedded = false
3943
self.embedded_relations = BSON::Document.new
4044
self.relations = BSON::Document.new
4145
self.aliased_associations = {}
46+
self.stored_as_associations = Set.new
4247
end
4348

4449
# This is convenience for libraries still on the old API.
@@ -219,6 +224,7 @@ def define_association!(macro_name, name, options = {}, &block)
219224
self.relations = self.relations.merge(name => assoc)
220225
if assoc.embedded? && assoc.respond_to?(:store_as) && assoc.store_as != name
221226
self.aliased_associations[assoc.store_as] = name
227+
self.stored_as_associations << assoc.store_as
222228
end
223229
end
224230
end

lib/mongoid/attributes/processing.rb

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,46 @@ 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-
4746
aliased = if aliased_associations.key?(name)
4847
aliased_associations[name]
4948
else
5049
name
5150
end
52-
5351
if relations.has_key?(aliased)
54-
pending_relations[name] = value
52+
set_pending_relation(name, aliased, value)
5553
return true
5654
end
5755
if nested_attributes.has_key?(aliased)
58-
pending_nested[name] = value
56+
set_pending_nested(name, aliased, value)
5957
return true
6058
end
61-
return false
59+
false
60+
end
61+
62+
# Set value of the pending relation.
63+
#
64+
# @param [ Symbol ] name The name of the relation.
65+
# @param [ Symbol ] aliased The aliased name of the relation.
66+
# @param [ Object ] value The value of the relation.
67+
def set_pending_relation(name, aliased, value)
68+
if stored_as_associations.include?(name)
69+
pending_relations[aliased] = value
70+
else
71+
pending_relations[name] = value
72+
end
73+
end
74+
75+
# Set value of the pending nested attribute.
76+
#
77+
# @param [ Symbol ] name The name of the nested attribute.
78+
# @param [ Symbol ] aliased The aliased name of the nested attribute.
79+
# @param [ Object ] value The value of the nested attribute.
80+
def set_pending_nested(name, aliased, value)
81+
if stored_as_associations.include?(name)
82+
pending_nested[aliased] = value
83+
else
84+
pending_nested[name] = value
85+
end
6286
end
6387

6488
# Get all the pending associations that need to be set.

spec/mongoid/attributes_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,4 +2711,31 @@
27112711
catalog.set_field.should == Set.new([ 1, 2 ])
27122712
end
27132713
end
2714+
2715+
context 'when an embedded field has a capitalized store_as name' do
2716+
let(:person) { Person.new(Purse: { brand: 'Gucci' }) }
2717+
2718+
it 'sets the value' do
2719+
expect(person.purse.brand).to eq('Gucci')
2720+
end
2721+
2722+
it 'saves successfully' do
2723+
expect(person.save!).to eq(true)
2724+
end
2725+
2726+
context 'when persisted' do
2727+
before do
2728+
person.save!
2729+
person.reload
2730+
end
2731+
2732+
it 'persists the value' do
2733+
expect(person.reload.purse.brand).to eq('Gucci')
2734+
end
2735+
2736+
it 'uses the correct key in the database' do
2737+
expect(person.collection.find(_id: person.id).first['Purse']['_id']).to eq(person.purse.id)
2738+
end
2739+
end
2740+
end
27142741
end

spec/support/models/person.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def find_by_street(street)
7070
embeds_many :messages, validate: false
7171

7272
embeds_one :passport, autobuild: true, store_as: :pass, validate: false
73+
embeds_one :purse, store_as: "Purse"
7374
embeds_one :pet, class_name: "Animal", validate: false
7475
embeds_one :name, as: :namable, validate: false do
7576
def extension

spec/support/models/purse.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
class Purse
4+
include Mongoid::Document
5+
6+
field :brand, type: String
7+
8+
embedded_in :person
9+
end

0 commit comments

Comments
 (0)