Skip to content

Commit c48ab14

Browse files
Merge pull request #20 from Couchbase-Ecosystem/handle_ignored_properties_on_nested_doc
Add support for ignored_properties on NestedDocument
2 parents 4ad1362 + e340e7f commit c48ab14

3 files changed

Lines changed: 78 additions & 3 deletions

File tree

lib/couchbase-orm/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Document
4646
include Encrypt
4747

4848
extend Enum
49+
extend IgnoredProperties
4950

5051
define_model_callbacks :initialize, :only => :after
5152

@@ -134,7 +135,6 @@ class Base < Document
134135
extend EnsureUnique
135136
extend HasMany
136137
extend Index
137-
extend IgnoredProperties
138138
extend JsonSchema::Validation
139139
extend PropertiesAlwaysExistsInDocument
140140

lib/couchbase-orm/types/nested.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,29 @@ def initialize(type:)
2626
def cast(value)
2727
return nil if value.nil?
2828
return value if value.is_a?(@model_class)
29-
return @model_class.new(value) if value.is_a?(Hash)
29+
30+
if value.is_a?(Hash)
31+
# Filter out ignored properties before creating the nested instance
32+
# Optimization: only call .except if there are properties to ignore
33+
ignored = @model_class.ignored_properties
34+
filtered_value = ignored.empty? ? value : value.except(*ignored)
35+
return @model_class.new(filtered_value)
36+
end
3037

3138
raise ArgumentError, "Nested: #{value.inspect} (#{value.class}) is not supported for cast"
3239
end
3340

3441
def serialize(value)
3542
return nil if value.nil?
36-
value = @model_class.new(value) if value.is_a?(Hash)
43+
44+
if value.is_a?(Hash)
45+
# Filter out ignored properties before creating the nested instance
46+
# Optimization: only call .except if there are properties to ignore
47+
ignored = @model_class.ignored_properties
48+
filtered_value = ignored.empty? ? value : value.except(*ignored)
49+
value = @model_class.new(filtered_value)
50+
end
51+
3752
return value.send(:serialized_attributes) if value.is_a?(@model_class)
3853

3954
raise ArgumentError, "Nested: #{value.inspect} (#{value.class}) is not supported for serialization"

spec/type_nested_spec.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,64 @@ class WithValidationParent < CouchbaseOrm::Base
188188
expect(obj.child.child.errors[:name]).to eq ["can't be blank"]
189189
end
190190
end
191+
192+
describe "Ignored Properties" do
193+
class SubTypeWithIgnoredProperties < CouchbaseOrm::NestedDocument
194+
self.ignored_properties = [:deprecated_property]
195+
attribute :name, :string
196+
attribute :value, :string
197+
end
198+
199+
class ParentWithNestedIgnoredProperties < CouchbaseOrm::Base
200+
self.ignored_properties = [:deprecated_at_root]
201+
attribute :title, :string
202+
attribute :nested, :nested, type: SubTypeWithIgnoredProperties
203+
end
204+
205+
it "should ignore deprecated properties in nested documents on reload" do
206+
# Create and save a parent with nested document
207+
parent = ParentWithNestedIgnoredProperties.new
208+
parent.title = "Test Parent"
209+
parent.nested = SubTypeWithIgnoredProperties.new(name: "Nested", value: "Valid")
210+
parent.save!
211+
212+
# Manually add a deprecated property to the nested document in the database
213+
doc_id = parent.id
214+
raw_doc = ParentWithNestedIgnoredProperties.bucket.default_collection.get(doc_id).content
215+
raw_doc["nested"]["deprecated_property"] = "This should be ignored"
216+
ParentWithNestedIgnoredProperties.bucket.default_collection.replace(doc_id, raw_doc)
217+
218+
# Reload the parent
219+
parent.reload
220+
221+
# The deprecated property should NOT be present in the nested document
222+
expect(parent.nested.attributes.keys).not_to include("deprecated_property")
223+
expect(parent.nested.name).to eq("Nested")
224+
expect(parent.nested.value).to eq("Valid")
225+
end
226+
227+
it "should ignore deprecated properties in deeply nested documents" do
228+
# Create a parent with nested documents that have a child
229+
parent = ParentWithNestedIgnoredProperties.new
230+
parent.title = "Test Parent"
231+
parent.nested = SubTypeWithIgnoredProperties.new(name: "Parent Nested", value: "Parent Value")
232+
parent.save!
233+
234+
# Manually add deprecated properties at multiple levels
235+
doc_id = parent.id
236+
raw_doc = ParentWithNestedIgnoredProperties.bucket.default_collection.get(doc_id).content
237+
raw_doc["deprecated_at_root"] = "Should be ignored at root level"
238+
raw_doc["nested"]["deprecated_property"] = "Should be ignored in nested"
239+
ParentWithNestedIgnoredProperties.bucket.default_collection.replace(doc_id, raw_doc)
240+
241+
# Reload the parent
242+
parent.reload
243+
244+
# Deprecated properties should not be present at any level
245+
expect(parent.attributes.keys).not_to include("deprecated_at_root")
246+
expect(parent.nested.attributes.keys).not_to include("deprecated_property")
247+
expect(parent.nested.name).to eq("Parent Nested")
248+
expect(parent.nested.value).to eq("Parent Value")
249+
end
250+
end
191251
end

0 commit comments

Comments
 (0)