Skip to content

Commit a7edd84

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 c8ae568 commit a7edd84

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
@@ -36,10 +36,15 @@ module Macros
3636
# @api private
3737
class_attribute :aliased_associations
3838

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

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

lib/mongoid/attributes/processing.rb

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,46 @@ def process_attributes(attrs = nil)
4444
# @return [ true | false ] True if pending, false if not.
4545
def pending_attribute?(key, value)
4646
name = key.to_s
47-
4847
aliased = if aliased_associations.key?(name)
4948
aliased_associations[name]
5049
else
5150
name
5251
end
53-
5452
if relations.has_key?(aliased)
55-
pending_relations[name] = value
53+
set_pending_relation(name, aliased, value)
5654
return true
5755
end
5856
if nested_attributes.has_key?(aliased)
59-
pending_nested[name] = value
57+
set_pending_nested(name, aliased, value)
6058
return true
6159
end
62-
return false
60+
false
61+
end
62+
63+
# Set value of the pending relation.
64+
#
65+
# @param [ Symbol ] name The name of the relation.
66+
# @param [ Symbol ] aliased The aliased name of the relation.
67+
# @param [ Object ] value The value of the relation.
68+
def set_pending_relation(name, aliased, value)
69+
if stored_as_associations.include?(name)
70+
pending_relations[aliased] = value
71+
else
72+
pending_relations[name] = value
73+
end
74+
end
75+
76+
# Set value of the pending nested attribute.
77+
#
78+
# @param [ Symbol ] name The name of the nested attribute.
79+
# @param [ Symbol ] aliased The aliased name of the nested attribute.
80+
# @param [ Object ] value The value of the nested attribute.
81+
def set_pending_nested(name, aliased, value)
82+
if stored_as_associations.include?(name)
83+
pending_nested[aliased] = value
84+
else
85+
pending_nested[name] = value
86+
end
6387
end
6488

6589
# 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
@@ -2707,4 +2707,31 @@
27072707
catalog.set_field.should == Set.new([ 1, 2 ])
27082708
end
27092709
end
2710+
2711+
context 'when an embedded field has a capitalized store_as name' do
2712+
let(:person) { Person.new(Purse: { brand: 'Gucci' }) }
2713+
2714+
it 'sets the value' do
2715+
expect(person.purse.brand).to eq('Gucci')
2716+
end
2717+
2718+
it 'saves successfully' do
2719+
expect(person.save!).to eq(true)
2720+
end
2721+
2722+
context 'when persisted' do
2723+
before do
2724+
person.save!
2725+
person.reload
2726+
end
2727+
2728+
it 'persists the value' do
2729+
expect(person.reload.purse.brand).to eq('Gucci')
2730+
end
2731+
2732+
it 'uses the correct key in the database' do
2733+
expect(person.collection.find(_id: person.id).first['Purse']['_id']).to eq(person.purse.id)
2734+
end
2735+
end
2736+
end
27102737
end

spec/support/models/person.rb

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

7373
embeds_one :passport, autobuild: true, store_as: :pass, validate: false
74+
embeds_one :purse, store_as: "Purse"
7475
embeds_one :pet, class_name: "Animal", validate: false
7576
embeds_one :name, as: :namable, validate: false do
7677
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)