diff --git a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelField+Association.swift b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelField+Association.swift index 98c1f82e9c..ec0a170d21 100644 --- a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelField+Association.swift +++ b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelField+Association.swift @@ -87,7 +87,7 @@ import Foundation /// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used /// directly by host applications. The behavior of this may change without warning. public enum ModelAssociation { - case hasMany(associatedFieldName: String?) + case hasMany(associatedFieldName: String?, associatedFieldNames: [String]) case hasOne(associatedFieldName: String?, targetNames: [String]) case belongsTo(associatedFieldName: String?, targetNames: [String]) @@ -98,8 +98,8 @@ public enum ModelAssociation { return .belongsTo(associatedFieldName: nil, targetNames: targetNames) } - public static func hasMany(associatedWith: CodingKey?) -> ModelAssociation { - return .hasMany(associatedFieldName: associatedWith?.stringValue) + public static func hasMany(associatedWith: CodingKey? = nil, associatedFields: [CodingKey] = []) -> ModelAssociation { + return .hasMany(associatedFieldName: associatedWith?.stringValue, associatedFieldNames: associatedFields.map { $0.stringValue }) } @available(*, deprecated, message: "Use hasOne(associatedWith:targetNames:)") @@ -234,13 +234,9 @@ extension ModelField { if hasAssociation { let associatedModel = requiredAssociatedModelName switch association { - case .belongsTo(let associatedKey, _): - // TODO handle modelName casing (convert to camelCase) - let key = associatedKey ?? associatedModel - let schema = ModelRegistry.modelSchema(from: associatedModel) - return schema?.field(withName: key) - case .hasOne(let associatedKey, _), - .hasMany(let associatedKey): + case .belongsTo(let associatedKey, _), + .hasOne(let associatedKey, _), + .hasMany(let associatedKey, _): // TODO handle modelName casing (convert to camelCase) let key = associatedKey ?? associatedModel let schema = ModelRegistry.modelSchema(from: associatedModel) diff --git a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelSchema+Definition.swift b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelSchema+Definition.swift index 7f5efaa1e6..dea9b39799 100644 --- a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelSchema+Definition.swift +++ b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelSchema+Definition.swift @@ -241,6 +241,18 @@ public enum ModelFieldDefinition { association: .hasMany(associatedWith: associatedKey)) } + public static func hasMany(_ key: CodingKey, + is nullability: ModelFieldNullability = .required, + isReadOnly: Bool = false, + ofType type: Model.Type, + associatedFields associatedKeys: [CodingKey]) -> ModelFieldDefinition { + return .field(key, + is: nullability, + isReadOnly: isReadOnly, + ofType: .collection(of: type), + association: .hasMany(associatedWith: associatedKeys.first ?? nil, associatedFields: associatedKeys)) + } + public static func hasOne(_ key: CodingKey, is nullability: ModelFieldNullability = .required, isReadOnly: Bool = false, diff --git a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/TestSupport/Mocks/TestModelRegistration.swift b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/TestSupport/Mocks/TestModelRegistration.swift index 73cf076da0..6dc6a6ef63 100644 --- a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/TestSupport/Mocks/TestModelRegistration.swift +++ b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/TestSupport/Mocks/TestModelRegistration.swift @@ -53,7 +53,7 @@ struct TestJsonModelRegistration: AmplifyModelRegistration { let comments = ModelField(name: "comments", type: .collection(of: "Comment"), isRequired: false, - association: .hasMany(associatedFieldName: "post")) + association: .hasMany(associatedFieldName: "post", associatedFieldNames: ["post"])) let postSchema = ModelSchema(name: "Post", listPluralName: "Posts", syncPluralName: "Posts", diff --git a/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift b/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift index e75a21bedb..c3e62f758e 100644 --- a/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift +++ b/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift @@ -28,7 +28,7 @@ class ModelFieldAssociationTests: XCTestCase { func testHasManyWithCodingKeys() { let hasMany = ModelAssociation.hasMany(associatedWith: Comment.keys.post) - guard case .hasMany(let fieldName) = hasMany else { + guard case .hasMany(let fieldName, _) = hasMany else { XCTFail("Should create hasMany association") return }