From 0c48936a50f4f9a5f155ec4294a26a1768cd00a1 Mon Sep 17 00:00:00 2001 From: johnnyshields <27655+johnnyshields@users.noreply.github.com> Date: Tue, 5 Sep 2023 00:55:51 +0900 Subject: [PATCH 1/6] __mongoize_fk step 1: move code to right class --- lib/mongoid/extensions/array.rb | 17 --- lib/mongoid/extensions/object.rb | 15 --- lib/mongoid/fields/foreign_key.rb | 25 +++- spec/mongoid/extensions/array_spec.rb | 150 ------------------------ spec/mongoid/extensions/object_spec.rb | 91 -------------- spec/mongoid/fields/foreign_key_spec.rb | 142 ++++++++++++++++++++++ 6 files changed, 166 insertions(+), 274 deletions(-) diff --git a/lib/mongoid/extensions/array.rb b/lib/mongoid/extensions/array.rb index 812ac620da..bba6d613a7 100644 --- a/lib/mongoid/extensions/array.rb +++ b/lib/mongoid/extensions/array.rb @@ -122,23 +122,6 @@ def resizable? module ClassMethods - # Convert the provided object to a proper array of foreign keys. - # - # @example Mongoize the object. - # Array.__mongoize_fk__(constraint, object) - # - # @param [ Mongoid::Association::Relatable ] association The association metadata. - # @param [ Object ] object The object to convert. - # - # @return [ Array ] The array of ids. - def __mongoize_fk__(association, object) - if object.resizable? - object.blank? ? object : association.convert_to_foreign_key(object) - else - object.blank? ? [] : association.convert_to_foreign_key(Array(object)) - end - end - # Turn the object from the ruby type we deal with to a Mongo friendly # type. # diff --git a/lib/mongoid/extensions/object.rb b/lib/mongoid/extensions/object.rb index ec0cd89f91..4d55ee10d2 100644 --- a/lib/mongoid/extensions/object.rb +++ b/lib/mongoid/extensions/object.rb @@ -203,21 +203,6 @@ def you_must(name, *args) module ClassMethods - # Convert the provided object to a foreign key, given the metadata key - # contstraint. - # - # @example Convert the object to a fk. - # Object.__mongoize_fk__(association, object) - # - # @param [ Mongoid::Association::Relatable ] association The association metadata. - # @param [ Object ] object The object to convert. - # - # @return [ Object ] The converted object. - def __mongoize_fk__(association, object) - return nil if !object || object == "" - association.convert_to_foreign_key(object) - end - # Convert the object from its mongo friendly ruby type to this type. # # @example Demongoize the object. diff --git a/lib/mongoid/fields/foreign_key.rb b/lib/mongoid/fields/foreign_key.rb index 19cb802ab9..5e0b7f1df3 100644 --- a/lib/mongoid/fields/foreign_key.rb +++ b/lib/mongoid/fields/foreign_key.rb @@ -95,7 +95,7 @@ def lazy? # @return [ Object ] The mongoized object. def mongoize(object) if type.resizable? || object_id_field? - type.__mongoize_fk__(association, object) + mongoize_foreign_key(type, association, object) else related_id_field.mongoize(object) end @@ -124,6 +124,29 @@ def resizable? private + # Convert the provided object to a foreign key, given the type + # and metadata key constraint. + # + # @example Convert the object to a fk. + # mongoize_foreign_key(Array, association, object) + # + # @param [ Class ] type The association metadata. + # @param [ Mongoid::Association::Relatable ] association The association metadata. + # @param [ Object ] object The object to convert. + # + # @return [ Object ] The converted object. + def mongoize_foreign_key(type, association, object) + if type == Array + if object.resizable? + object.blank? ? object : association.convert_to_foreign_key(object) + else + object.blank? ? [] : association.convert_to_foreign_key(Array(object)) + end + elsif !(object.nil? || object == '') + association.convert_to_foreign_key(object) + end + end + # Evaluate the default proc. In some cases we need to instance exec, # in others we don't. # diff --git a/spec/mongoid/extensions/array_spec.rb b/spec/mongoid/extensions/array_spec.rb index 18ab1ee2f2..4019f6f1c2 100644 --- a/spec/mongoid/extensions/array_spec.rb +++ b/spec/mongoid/extensions/array_spec.rb @@ -203,156 +203,6 @@ end end - describe ".__mongoize_fk__" do - - context "when the related model uses object ids" do - - let(:association) do - Person.relations["preferences"] - end - - context "when provided an object id" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Array.__mongoize_fk__(association, object_id) - end - - it "returns the object id as an array" do - expect(fk).to eq([ object_id ]) - end - end - - context "when provided a object ids" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Array.__mongoize_fk__(association, [ object_id ]) - end - - it "returns the object ids" do - expect(fk).to eq([ object_id ]) - end - end - - context "when provided a string" do - - context "when the string is a legal object id" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Array.__mongoize_fk__(association, object_id.to_s) - end - - it "returns the object id in an array" do - expect(fk).to eq([ object_id ]) - end - end - - context "when the string is not a legal object id" do - - let(:string) do - "blah" - end - - let(:fk) do - Array.__mongoize_fk__(association, string) - end - - it "returns the string in an array" do - expect(fk).to eq([ string ]) - end - end - - context "when the string is blank" do - - let(:fk) do - Array.__mongoize_fk__(association, "") - end - - it "returns an empty array" do - expect(fk).to be_empty - end - end - end - - context "when provided nil" do - - let(:fk) do - Array.__mongoize_fk__(association, nil) - end - - it "returns an empty array" do - expect(fk).to be_empty - end - end - - context "when provided an array of strings" do - - context "when the strings are legal object ids" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Array.__mongoize_fk__(association, [ object_id.to_s ]) - end - - it "returns the object id in an array" do - expect(fk).to eq([ object_id ]) - end - end - - context "when the strings are not legal object ids" do - - let(:string) do - "blah" - end - - let(:fk) do - Array.__mongoize_fk__(association, [ string ]) - end - - it "returns the string in an array" do - expect(fk).to eq([ string ]) - end - end - - context "when the strings are blank" do - - let(:fk) do - Array.__mongoize_fk__(association, [ "", "" ]) - end - - it "returns an empty array" do - expect(fk).to be_empty - end - end - end - - context "when provided nils" do - - let(:fk) do - Array.__mongoize_fk__(association, [ nil, nil, nil ]) - end - - it "returns an empty array" do - expect(fk).to be_empty - end - end - end - end - describe "#__mongoize_time__" do let(:array) do diff --git a/spec/mongoid/extensions/object_spec.rb b/spec/mongoid/extensions/object_spec.rb index 80d313a3af..e610285798 100644 --- a/spec/mongoid/extensions/object_spec.rb +++ b/spec/mongoid/extensions/object_spec.rb @@ -30,97 +30,6 @@ end end - describe ".__mongoize_fk__" do - - context "when the related model uses object ids" do - - let(:association) do - Game.relations["person"] - end - - context "when provided an object id" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Object.__mongoize_fk__(association, object_id) - end - - it "returns the object id" do - expect(fk).to eq(object_id) - end - end - - context "when provided a string" do - - context "when the string is a legal object id" do - - let(:object_id) do - BSON::ObjectId.new - end - - let(:fk) do - Object.__mongoize_fk__(association, object_id.to_s) - end - - it "returns the object id" do - expect(fk).to eq(object_id) - end - end - - context "when the string is not a legal object id" do - - let(:string) do - "blah" - end - - let(:fk) do - Object.__mongoize_fk__(association, string) - end - - it "returns the string" do - expect(fk).to eq(string) - end - end - - context "when the string is blank" do - - let(:fk) do - Object.__mongoize_fk__(association, "") - end - - it "returns nil" do - expect(fk).to be_nil - end - end - end - - context "when provided nil" do - - let(:fk) do - Object.__mongoize_fk__(association, nil) - end - - it "returns nil" do - expect(fk).to be_nil - end - end - - context "when provided an empty array" do - - let(:fk) do - Object.__mongoize_fk__(association, []) - end - - it "returns an empty array" do - expect(fk).to eq([]) - end - end - end - end - describe "#__mongoize_time__" do it "returns self" do diff --git a/spec/mongoid/fields/foreign_key_spec.rb b/spec/mongoid/fields/foreign_key_spec.rb index 3aafef65a5..15878a360c 100644 --- a/spec/mongoid/fields/foreign_key_spec.rb +++ b/spec/mongoid/fields/foreign_key_spec.rb @@ -716,4 +716,146 @@ end end end + + describe "#mongoize_foreign_key" do + let(:field) { described_class.new(:vals, type: Object, default: []) } + let(:association) { Person.relations['preferences'] } + subject(:mongoized) { field.send(:mongoize_foreign_key, type, association, object) } + + context 'type is Array' do + let(:type) { Array } + + context 'when the object is a BSON::ObjectId' do + let(:object) { BSON::ObjectId.new } + + it 'returns the object id as an array' do + expect(mongoized).to eq([object]) + end + end + + context 'when the object is an Array of BSON::ObjectId' do + let(:object) { [BSON::ObjectId.new] } + + it 'returns the object ids' do + expect(mongoized).to eq(object) + end + end + + context 'when the object is a String which is a legal object id' do + let(:object) { BSON::ObjectId.new.to_s } + + it 'returns the object id in an array' do + expect(mongoized).to eq([BSON::ObjectId.from_string(object)]) + end + end + + context 'when the object is a String which is not a legal object id' do + let(:object) { 'blah' } + + it 'returns the object id in an array' do + expect(mongoized).to eq(%w[blah]) + end + end + + context 'when the object is a blank String' do + let(:object) { '' } + + it 'returns an empty array' do + expect(mongoized).to eq([]) + end + end + + context 'when the object is nil' do + let(:object) { nil } + + it 'returns an empty array' do + expect(mongoized).to eq([]) + end + end + + context 'when the object is Array of Strings which are legal object ids' do + let(:object) { [BSON::ObjectId.new.to_s] } + + it 'returns the object id in an array' do + expect(mongoized).to eq([BSON::ObjectId.from_string(object.first)]) + end + end + + context 'when the object is Array of Strings which are not legal object ids' do + let(:object) { %w[blah] } + + it 'returns the object id in an array' do + expect(mongoized).to eq(%w[blah]) + end + end + + context 'when the object is Array of Strings which are blank' do + let(:object) { ['', ''] } + + it 'returns the object id in an array' do + expect(mongoized).to eq([]) + end + end + + context 'when the object is Array of nils' do + let(:object) { [nil, nil, nil] } + + it 'returns the object id in an array' do + expect(mongoized).to eq([]) + end + end + end + + context 'type is not Array' do + let(:type) { Object } + + context 'when the object is a BSON::ObjectId' do + let(:object) { BSON::ObjectId.new } + + it 'returns the object id' do + expect(mongoized).to eq(object) + end + end + + context 'when the object is a String which is a legal object id' do + let(:object) { BSON::ObjectId.new.to_s } + + it 'returns the object id' do + expect(mongoized).to eq(BSON::ObjectId.from_string(object)) + end + end + + context 'when the object is a String which is not a legal object id' do + let(:object) { 'blah' } + + it 'returns the string' do + expect(mongoized).to eq('blah') + end + end + + context 'when the String is blank' do + let(:object) { '' } + + it 'returns nil' do + expect(mongoized).to be_nil + end + end + + context 'when the object is nil' do + let(:object) { '' } + + it 'returns nil' do + expect(mongoized).to be_nil + end + end + + context 'when object is an empty Array' do + let(:object) { [] } + + it 'returns an empty array' do + expect(mongoized).to eq([]) + end + end + end + end end From b74ce466ac022ea65aee3de57ca486f47cc52eb0 Mon Sep 17 00:00:00 2001 From: johnnyshields <27655+johnnyshields@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:01:02 +0900 Subject: [PATCH 2/6] __mongoize_fk step 1: #mongoize_foreign_key should use class member variables --- lib/mongoid/fields/foreign_key.rb | 12 +++++------- spec/mongoid/fields/foreign_key_spec.rb | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/mongoid/fields/foreign_key.rb b/lib/mongoid/fields/foreign_key.rb index 5e0b7f1df3..774acd9599 100644 --- a/lib/mongoid/fields/foreign_key.rb +++ b/lib/mongoid/fields/foreign_key.rb @@ -14,7 +14,7 @@ class ForeignKey < Standard # @example Add the atomic changes. # field.add_atomic_changes(doc, "key", {}, [], []) # - # @todo: Durran: Refactor, big time. + # @todo: Refactor, big time. # # @param [ Document ] document The document to add to. # @param [ String ] name The name of the field. @@ -95,7 +95,7 @@ def lazy? # @return [ Object ] The mongoized object. def mongoize(object) if type.resizable? || object_id_field? - mongoize_foreign_key(type, association, object) + mongoize_foreign_key(object) else related_id_field.mongoize(object) end @@ -127,15 +127,13 @@ def resizable? # Convert the provided object to a foreign key, given the type # and metadata key constraint. # - # @example Convert the object to a fk. - # mongoize_foreign_key(Array, association, object) + # @example Convert the object to a foreign key. + # mongoize_foreign_key(object) # - # @param [ Class ] type The association metadata. - # @param [ Mongoid::Association::Relatable ] association The association metadata. # @param [ Object ] object The object to convert. # # @return [ Object ] The converted object. - def mongoize_foreign_key(type, association, object) + def mongoize_foreign_key(object) if type == Array if object.resizable? object.blank? ? object : association.convert_to_foreign_key(object) diff --git a/spec/mongoid/fields/foreign_key_spec.rb b/spec/mongoid/fields/foreign_key_spec.rb index 15878a360c..5357a57611 100644 --- a/spec/mongoid/fields/foreign_key_spec.rb +++ b/spec/mongoid/fields/foreign_key_spec.rb @@ -718,9 +718,9 @@ end describe "#mongoize_foreign_key" do - let(:field) { described_class.new(:vals, type: Object, default: []) } + let(:field) { described_class.new(:vals, type: type, association: association) } let(:association) { Person.relations['preferences'] } - subject(:mongoized) { field.send(:mongoize_foreign_key, type, association, object) } + subject(:mongoized) { field.send(:mongoize_foreign_key, object) } context 'type is Array' do let(:type) { Array } From dc6646b76996f0b83a46c6c766a9655cc11880ad Mon Sep 17 00:00:00 2001 From: johnnyshields <27655+johnnyshields@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:41:07 +0900 Subject: [PATCH 3/6] __mongoize_fk step 3: consolidate all specs to public #mongoize method --- lib/mongoid/fields/foreign_key.rb | 2 +- spec/mongoid/fields/foreign_key_spec.rb | 480 ++++++++++++------------ 2 files changed, 251 insertions(+), 231 deletions(-) diff --git a/lib/mongoid/fields/foreign_key.rb b/lib/mongoid/fields/foreign_key.rb index 774acd9599..484b960af0 100644 --- a/lib/mongoid/fields/foreign_key.rb +++ b/lib/mongoid/fields/foreign_key.rb @@ -134,7 +134,7 @@ def resizable? # # @return [ Object ] The converted object. def mongoize_foreign_key(object) - if type == Array + if type == Array || type == Set if object.resizable? object.blank? ? object : association.convert_to_foreign_key(object) else diff --git a/spec/mongoid/fields/foreign_key_spec.rb b/spec/mongoid/fields/foreign_key_spec.rb index 5357a57611..fedfef3eca 100644 --- a/spec/mongoid/fields/foreign_key_spec.rb +++ b/spec/mongoid/fields/foreign_key_spec.rb @@ -497,230 +497,19 @@ end end - describe "#mongoize" do - - context "when the type is array" do - - context "when the array is object ids" do - - let(:association) do - Game.relations["person"] - end - - let(:field) do - described_class.new( - :vals, - type: Array, - default: [], - identity: true, - association: association, - overwrite: true - ) - end - - context "when provided nil" do - - it "returns an empty array" do - expect(field.mongoize(nil)).to be_empty - end - end - - context "when provided an empty array" do - - let(:array) do - [] - end - - it "returns an empty array" do - expect(field.mongoize(array)).to eq(array) - end - - it "returns the same instance" do - expect(field.mongoize(array)).to equal(array) - end - end - - context "when using object ids" do - - let(:object_id) do - BSON::ObjectId.new - end - - it "performs conversion on the ids if strings" do - expect(field.mongoize([object_id.to_s])).to eq([object_id]) - end - end - - context "when not using object ids" do - - let(:object_id) do - BSON::ObjectId.new - end - - before do - Person.field( - :_id, - type: String, - pre_processed: true, - default: ->{ BSON::ObjectId.new.to_s }, - overwrite: true - ) - end - - after do - Person.field( - :_id, - type: BSON::ObjectId, - pre_processed: true, - default: ->{ BSON::ObjectId.new }, - overwrite: true - ) - end - - it "does not convert" do - expect(field.mongoize([object_id.to_s])).to eq([object_id.to_s]) - end - end - end - end - - context "when the type is object" do - - context "when the array is object ids" do - - let(:association) do - Game.relations['person'] - end - - let(:field) do - described_class.new( - :vals, - type: Object, - default: nil, - identity: true, - association: association, - overwrite: true - ) - end - - context "when using object ids" do - - let(:object_id) do - BSON::ObjectId.new - end - - it "performs conversion on the ids if strings" do - expect(field.mongoize(object_id.to_s)).to eq(object_id) - end - end - - context "when not using object ids" do - - context "when using strings" do - - context "when provided a string" do - - let(:object_id) do - BSON::ObjectId.new - end - - before do - Person.field( - :_id, - type: String, - pre_processed: true, - default: ->{ BSON::ObjectId.new.to_s }, - overwrite: true - ) - end - - after do - Person.field( - :_id, - type: BSON::ObjectId, - pre_processed: true, - default: ->{ BSON::ObjectId.new }, - overwrite: true - ) - end - - it "does not convert" do - expect(field.mongoize(object_id.to_s)).to eq(object_id.to_s) - end - end - end - - context "when using integers" do - - context "when provided a string" do - - before do - Person.field(:_id, type: Integer, overwrite: true) - end - - after do - Person.field( - :_id, - type: BSON::ObjectId, - pre_processed: true, - default: ->{ BSON::ObjectId.new }, - overwrite: true - ) - end - - it "converts the string to an integer" do - expect(field.mongoize("1")).to eq(1) - end - end - end - end - end - end - end - - describe "#resizable" do - - context "when the type is an array" do - - let(:field) do - described_class.new(:vals, type: Array, default: []) - end - - it "returns true" do - expect(field).to be_resizable - end - end - - context "when the type is an object" do - - let(:field) do - described_class.new(:vals, type: Object, default: []) - end - - it "returns false" do - expect(field).to_not be_resizable - end - end - end - - context "when the foreign key points is a many to many" do - - context "when the related document stores non object ids" do - - let(:agent) do - Agent.new(account_ids: [ true, false, 1, 2 ]) - end - - it "casts the ids on the initial set" do - expect(agent.account_ids).to eq([ "true", "false", "1", "2" ]) - end + describe '#mongoize' do + let(:field) do + described_class.new( + :vals, + type: type, + default: [], + identity: true, + association: association, + overwrite: true + ) end - end - - describe "#mongoize_foreign_key" do - let(:field) { described_class.new(:vals, type: type, association: association) } - let(:association) { Person.relations['preferences'] } - subject(:mongoized) { field.send(:mongoize_foreign_key, object) } + let(:association) { Game.relations['person'] } + subject(:mongoized) { field.mongoize(object) } context 'type is Array' do let(:type) { Array } @@ -784,7 +573,7 @@ context 'when the object is Array of Strings which are not legal object ids' do let(:object) { %w[blah] } - it 'returns the object id in an array' do + it 'returns the Array' do expect(mongoized).to eq(%w[blah]) end end @@ -792,21 +581,133 @@ context 'when the object is Array of Strings which are blank' do let(:object) { ['', ''] } - it 'returns the object id in an array' do + it 'returns an empty Array' do expect(mongoized).to eq([]) end end context 'when the object is Array of nils' do - let(:object) { [nil, nil, nil] } + let(:object) { [nil, nil, nil] } + + it 'returns an empty Array' do + expect(mongoized).to eq([]) + end + end + + context 'when the object is an empty Array' do + let(:object) { [] } + + it 'returns an empty Array' do + expect(mongoized).to eq([]) + end + + it 'returns the same instance' do + expect(mongoized).to equal(object) + end + end + + context 'when the object is a Set' do + let(:object) { Set['blah'] } + + it 'returns the object id in an array' do + expect(mongoized).to eq(%w[blah]) + end + end + + context 'when foreign key is a String' do + before do + Person.field(:_id, type: String, overwrite: true) + end + + after do + Person.field( + :_id, + type: BSON::ObjectId, + pre_processed: true, + default: ->{ BSON::ObjectId.new }, + overwrite: true + ) + end + + context 'when the object is a String' do + let(:object) { %w[1] } + + it 'returns String' do + expect(mongoized).to eq(object) + end + end + + context 'when the object is a BSON::ObjectId' do + let(:object) { [BSON::ObjectId.new] } + + it 'converts to String' do + expect(mongoized).to eq([object.first.to_s]) + end + end + + context 'when the object is an Integer' do + let(:object) { [1] } + + it 'converts to String' do + expect(mongoized).to eq(%w[1]) + end + end + end + + context 'when foreign key is an Integer' do + before do + Person.field(:_id, type: Integer, overwrite: true) + end + + after do + Person.field( + :_id, + type: BSON::ObjectId, + pre_processed: true, + default: ->{ BSON::ObjectId.new }, + overwrite: true + ) + end + + context 'when the object is a String' do + let(:object) { %w[1] } - it 'returns the object id in an array' do - expect(mongoized).to eq([]) + it 'converts to Integer' do + expect(mongoized).to eq([1]) end end + + context 'when the object is an Integer' do + let(:object) { [1] } + + it 'returns Integer' do + expect(mongoized).to eq([1]) + end + end + end end - context 'type is not Array' do + context 'type is Set' do + let(:type) { Set } + + context 'when the object is an Array of BSON::ObjectId' do + let(:object) { [BSON::ObjectId.new] } + + it 'returns the object ids' do + expect(mongoized).to eq(object) + end + end + + context 'when the object is a Set of BSON::ObjectId' do + let(:object) { Set[BSON::ObjectId.new] } + + it 'returns the object id in an array' do + expect(mongoized).to eq([object.first]) + end + end + end + + context 'type is Object' do let(:type) { Object } context 'when the object is a BSON::ObjectId' do @@ -839,7 +740,7 @@ it 'returns nil' do expect(mongoized).to be_nil end - end + end context 'when the object is nil' do let(:object) { '' } @@ -856,6 +757,125 @@ expect(mongoized).to eq([]) end end + + context 'when the object is a Set' do + let(:object) { Set['blah'] } + + it 'returns the set' do + expect(mongoized).to eq(Set['blah']) + end + end + + context 'when foreign key is a String' do + before do + Person.field(:_id, type: String, overwrite: true) + end + + after do + Person.field( + :_id, + type: BSON::ObjectId, + pre_processed: true, + default: ->{ BSON::ObjectId.new }, + overwrite: true + ) + end + + context 'when the object is a String' do + let(:object) { '1' } + + it 'returns String' do + expect(mongoized).to eq(object) + end + end + + context 'when the object is a BSON::ObjectId' do + let(:object) { BSON::ObjectId.new } + + it 'converts to String' do + expect(mongoized).to eq(object.to_s) + end + end + + context 'when the object is an Integer' do + let(:object) { 1 } + + it 'converts to String' do + expect(mongoized).to eq('1') + end + end + end + + context 'when foreign key is an Integer' do + before do + Person.field(:_id, type: Integer, overwrite: true) + end + + after do + Person.field( + :_id, + type: BSON::ObjectId, + pre_processed: true, + default: ->{ BSON::ObjectId.new }, + overwrite: true + ) + end + + context 'when the object is a String' do + let(:object) { '1' } + + it 'converts to Integer' do + expect(mongoized).to eq(1) + end + end + + context 'when the object is an Integer' do + let(:object) { 1 } + + it 'returns Integer' do + expect(mongoized).to eq(object) + end + end + end + end + end + + describe "#resizable" do + + context "when the type is an array" do + + let(:field) do + described_class.new(:vals, type: Array, default: []) + end + + it "returns true" do + expect(field).to be_resizable + end + end + + context "when the type is an object" do + + let(:field) do + described_class.new(:vals, type: Object, default: []) + end + + it "returns false" do + expect(field).to_not be_resizable + end + end + end + + context "when the foreign key points is a many to many" do + + context "when the related document stores non object ids" do + + let(:agent) do + Agent.new(account_ids: [ true, false, 1, 2 ]) + end + + it "casts the ids on the initial set" do + expect(agent.account_ids).to eq([ "true", "false", "1", "2" ]) + end end end end From 88fce3ac9665117c97a5f04c6f0333ee7721acf0 Mon Sep 17 00:00:00 2001 From: Johnny Shields <27655+johnnyshields@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:48:15 +0900 Subject: [PATCH 4/6] Update foreign_key.rb --- lib/mongoid/fields/foreign_key.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/mongoid/fields/foreign_key.rb b/lib/mongoid/fields/foreign_key.rb index 484b960af0..2b8b558a90 100644 --- a/lib/mongoid/fields/foreign_key.rb +++ b/lib/mongoid/fields/foreign_key.rb @@ -124,8 +124,7 @@ def resizable? private - # Convert the provided object to a foreign key, given the type - # and metadata key constraint. + # Convert the provided object to a Mongo-friendly foreign key. # # @example Convert the object to a foreign key. # mongoize_foreign_key(object) From a3e295ba845c9bff729925e1a85119261ef40a29 Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Wed, 8 Nov 2023 09:19:08 -0700 Subject: [PATCH 5/6] deprecate, rather than remove --- lib/mongoid/extensions/array.rb | 19 +++++++++++++++++++ lib/mongoid/extensions/object.rb | 2 ++ 2 files changed, 21 insertions(+) diff --git a/lib/mongoid/extensions/array.rb b/lib/mongoid/extensions/array.rb index cf5cf0656a..6ff0d75c51 100644 --- a/lib/mongoid/extensions/array.rb +++ b/lib/mongoid/extensions/array.rb @@ -105,6 +105,25 @@ def resizable? module ClassMethods + # Convert the provided object to a proper array of foreign keys. + # + # @example Mongoize the object. + # Array.__mongoize_fk__(constraint, object) + # + # @param [ Mongoid::Association::Relatable ] association The association metadata. + # @param [ Object ] object The object to convert. + # + # @return [ Array ] The array of ids. + # @deprecated + def __mongoize_fk__(association, object) + if object.resizable? + object.blank? ? object : association.convert_to_foreign_key(object) + else + object.blank? ? [] : association.convert_to_foreign_key(Array(object)) + end + end + Mongoid.deprecate(self, :__mongoize_fk__) + # Turn the object from the ruby type we deal with to a Mongo friendly # type. # diff --git a/lib/mongoid/extensions/object.rb b/lib/mongoid/extensions/object.rb index 495f7b2c40..879602f39e 100644 --- a/lib/mongoid/extensions/object.rb +++ b/lib/mongoid/extensions/object.rb @@ -215,10 +215,12 @@ module ClassMethods # @param [ Object ] object The object to convert. # # @return [ Object ] The converted object. + # @deprecated def __mongoize_fk__(association, object) return nil if !object || object == "" association.convert_to_foreign_key(object) end + Mongoid.deprecate(self, :__mongoize_fk__) # Convert the object from its mongo friendly ruby type to this type. # From 7aebf023710c1744dfff4953177d9baabefd3174 Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Wed, 8 Nov 2023 13:19:00 -0700 Subject: [PATCH 6/6] Set support requires a bit of baby-sitting... --- lib/mongoid/fields/foreign_key.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mongoid/fields/foreign_key.rb b/lib/mongoid/fields/foreign_key.rb index 2b8b558a90..815d5cdc99 100644 --- a/lib/mongoid/fields/foreign_key.rb +++ b/lib/mongoid/fields/foreign_key.rb @@ -134,6 +134,8 @@ def resizable? # @return [ Object ] The converted object. def mongoize_foreign_key(object) if type == Array || type == Set + object = object.to_a if type == Set || object.is_a?(Set) + if object.resizable? object.blank? ? object : association.convert_to_foreign_key(object) else