Skip to content

Commit 4223288

Browse files
authored
DEV: Correctly validate multiple uploads in object site setting (#36639)
# Bug The Setup: - Object site setting has 2 upload fields: UPLOAD_FIELD_1 and UPLOAD_FIELD_2 - Frontend sends URLs for both fields to the backend - Backend needs to convert URLs → IDs and validate them ## The Problem Validation loop processes properties one by one: ### 1. Validate UPLOAD_FIELD_1 - Convert URL → ID (123) - Check if ID is valid by querying: Upload.where(id: fetch_all_upload_values) - fetch_all_upload_values returns: [123, "http://mobile.png"] ← MIXED TYPES! - Query only finds Upload 123 - Cache valid_ids = [123] ← MEMOIZED ### 2. Validate UPLOAD_FIELD_2 - Convert URL → ID (456) - Check if ID is valid using cached valid_ids - valid_ids = [123] ← Still cached from step 1! - ID 456 not in [123] → VALIDATION FAILS ❌ Why it failed: When validating the first upload, the validation logic tried to fetch ALL upload values to check validity. But the second upload was still a URL string, not an ID yet. This created a mixed array [123, "http://..."] that couldn't be properly queried. The cached result then excluded the second upload, causing it to fail validation. # Fix Convert ALL URLs → IDs in first pass, THEN validate everything in second pass. Now when the validation queries run, all values are already integers.
1 parent 9d1bfb7 commit 4223288

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

lib/schema_settings_object_validator.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ def initialize(schema:, object:, json_pointer_prefix: "", errors: {}, valid_ids_
8080
end
8181

8282
def validate
83+
# Convert all upload URLs to IDs before validation
84+
@properties.each do |property_name, property_attributes|
85+
next if property_attributes[:type] != "upload"
86+
normalize_upload_value(property_name, property_attributes)
87+
end
88+
89+
# Validate all properties
8390
@properties.each do |property_name, property_attributes|
8491
if property_attributes[:type] == "objects"
8592
validate_child_objects(
@@ -101,6 +108,15 @@ def property_values_of_type(type)
101108

102109
private
103110

111+
def normalize_upload_value(property_name, property_attributes)
112+
value = @object[property_name]
113+
return unless value.is_a?(String) && value.present?
114+
115+
if upload = Upload.get_from_url(value)
116+
@object[property_name] = upload.id
117+
end
118+
end
119+
104120
def validate_child_objects(objects, property_name:, schema:)
105121
return if objects.blank?
106122

@@ -137,18 +153,8 @@ def has_valid_property_value_type?(property_attributes, property_name)
137153
when "integer", "topic", "post"
138154
value.is_a?(Integer)
139155
when "upload"
140-
# Convert upload URLs to IDs like core does
141-
if value.is_a?(String)
142-
upload = Upload.get_from_url(value)
143-
if upload
144-
@object[property_name] = upload.id
145-
true
146-
else
147-
false
148-
end
149-
else
150-
value.is_a?(Integer)
151-
end
156+
# Upload URLs are converted to IDs in normalize_upload_value
157+
value.is_a?(Integer)
152158
when "float"
153159
value.is_a?(Float) || value.is_a?(Integer)
154160
when "boolean"

spec/lib/schema_settings_object_validator_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,30 @@ def schema(required: false)
800800
# only 1 SQL query should be executed to check if upload ids are valid
801801
expect(queries.length).to eq(1)
802802
end
803+
804+
it "should convert multiple upload URLs to IDs and validate successfully" do
805+
upload1 = Fabricate(:upload)
806+
upload2 = Fabricate(:upload)
807+
schema = {
808+
name: "section",
809+
properties: {
810+
upload_property_1: {
811+
type: "upload",
812+
},
813+
upload_property_2: {
814+
type: "upload",
815+
},
816+
},
817+
}
818+
819+
object = { upload_property_1: upload1.url, upload_property_2: upload2.url }
820+
validator = described_class.new(schema: schema, object: object)
821+
errors = validator.validate
822+
823+
expect(errors).to eq({})
824+
expect(validator.instance_variable_get(:@object)[:upload_property_1]).to eq(upload1.id)
825+
expect(validator.instance_variable_get(:@object)[:upload_property_2]).to eq(upload2.id)
826+
end
803827
end
804828

805829
context "for tag properties" do

0 commit comments

Comments
 (0)