Skip to content

Commit

Permalink
fix(data): Gen2 hasOne associatedFields compile issue (#3700)
Browse files Browse the repository at this point in the history
  • Loading branch information
lawmicha authored Jul 16, 2024
1 parent 12511d1 commit e886cf0
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import Foundation
/// directly by host applications. The behavior of this may change without warning.
public enum ModelAssociation {
case hasMany(associatedFieldName: String?, associatedFieldNames: [String] = [])
case hasOne(associatedFieldName: String?, targetNames: [String])
case hasOne(associatedFieldName: String?, associatedFieldNames: [String] = [], targetNames: [String])
case belongsTo(associatedFieldName: String?, targetNames: [String])

public static let belongsTo: ModelAssociation = .belongsTo(associatedFieldName: nil, targetNames: [])
Expand All @@ -108,14 +108,20 @@ public enum ModelAssociation {
)
}

@available(*, deprecated, message: "Use hasOne(associatedWith:targetNames:)")
@available(*, deprecated, message: "Use hasOne(associatedWith:associatedFields:targetNames:)")
public static func hasOne(associatedWith: CodingKey?, targetName: String? = nil) -> ModelAssociation {
let targetNames = targetName.map { [$0] } ?? []
return .hasOne(associatedWith: associatedWith, targetNames: targetNames)
}

public static func hasOne(associatedWith: CodingKey?, targetNames: [String] = []) -> ModelAssociation {
return .hasOne(associatedFieldName: associatedWith?.stringValue, targetNames: targetNames)
public static func hasOne(
associatedWith: CodingKey? = nil,
associatedFields: [CodingKey] = [],
targetNames: [String] = []) -> ModelAssociation {
return .hasOne(
associatedFieldName: associatedWith?.stringValue,
associatedFieldNames: associatedFields.map { $0.stringValue },
targetNames: targetNames)
}

@available(*, deprecated, message: "Use belongsTo(associatedWith:targetNames:)")
Expand Down Expand Up @@ -254,7 +260,7 @@ extension ModelField {
let associatedModel = requiredAssociatedModelName
switch association {
case .belongsTo(let associatedKey, _),
.hasOne(let associatedKey, _),
.hasOne(let associatedKey, _, _),
.hasMany(let associatedKey, _):
// TODO handle modelName casing (convert to camelCase)
let key = associatedKey ?? associatedModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,21 @@ public enum ModelFieldDefinition {
association: .hasOne(associatedWith: associatedKey, targetNames: targetNames))
}

public static func hasOne(_ key: CodingKey,
is nullability: ModelFieldNullability = .required,
isReadOnly: Bool = false,
ofType type: Model.Type,
associatedFields associatedKeys: [CodingKey],
targetNames: [String] = []) -> ModelFieldDefinition {
return .field(key,
is: nullability,
isReadOnly: isReadOnly,
ofType: .model(type: type),
association: .hasOne(associatedWith: associatedKeys.first,
associatedFields: associatedKeys,
targetNames: targetNames))
}

public static func belongsTo(_ key: CodingKey,
is nullability: ModelFieldNullability = .required,
isReadOnly: Bool = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public class AppSyncListProvider<Element: Model>: ModelListProvider {
}
let defaultFieldName = modelSchema.name.camelCased() + field.pascalCased() + "Id"
switch modelField.association {
case .belongsTo(_, let targetNames), .hasOne(_, let targetNames):
case .belongsTo(_, let targetNames), .hasOne(_, _, let targetNames):
guard !targetNames.isEmpty else {
return [defaultFieldName]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension Customer4 {
model.fields(
.field(customer4.id, is: .required, ofType: .string),
.field(customer4.name, is: .optional, ofType: .string),
.hasOne(customer4.activeCart, is: .optional, ofType: Cart4.self, associatedWith: Cart4.keys.customer),
.hasOne(customer4.activeCart, is: .optional, ofType: Cart4.self, associatedFields: [Cart4.keys.customer]),
.field(customer4.createdAt, is: .optional, isReadOnly: true, ofType: .dateTime),
.field(customer4.updatedAt, is: .optional, isReadOnly: true, ofType: .dateTime)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ extension Model {
let defaultFieldName = modelName.camelCased() + modelField.name.pascalCased() + "Id"
if case let .belongsTo(_, targetNames) = modelField.association, !targetNames.isEmpty {
return targetNames
} else if case let .hasOne(_, targetNames) = modelField.association,
} else if case let .hasOne(_, _, targetNames) = modelField.association,
!targetNames.isEmpty {
return targetNames
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ extension QueryPredicateOperation: GraphQLFilterConvertible {
}
let targetName = targetNames.first ?? defaultFieldName
return targetName
case .hasOne(_, let targetNames):
case .hasOne(_, _, let targetNames):
guard targetNames.count == 1 else {
preconditionFailure("QueryPredicate not supported on associated field with composite key: \(field)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension ModelField: SQLColumn {
var sqlName: String {
if case let .belongsTo(_, targetNames) = association {
return foreignKeySqlName(withAssociationTargets: targetNames)
} else if case let .hasOne(_, targetNames) = association {
} else if case let .hasOne(_, _, targetNames) = association {
return foreignKeySqlName(withAssociationTargets: targetNames)
}
return name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ extension Statement: StatementModelConvertible {

private func getTargetNames(field: ModelField) -> [String] {
switch field.association {
case let .some(.hasOne(_, targetNames)):
case let .some(.hasOne(_, _, targetNames)):
return targetNames
case let .some(.belongsTo(_, targetNames)):
return targetNames
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,37 @@ class ModelFieldAssociationTests: XCTestCase {

func testHasOneWithCodingKeys() {
let hasOne = ModelAssociation.hasOne(associatedWith: Comment.keys.post, targetNames: [])
guard case .hasOne(let fieldName, let target) = hasOne else {
guard case .hasOne(let fieldName, let fieldNames, let target) = hasOne else {
XCTFail("Should create hasOne association")
return
}
XCTAssertEqual(fieldName, Comment.keys.post.stringValue)
XCTAssertEqual(fieldNames, [])
XCTAssertEqual(target, [])
}

func testHasOneWithCodingKeysWithTargetName() {
let hasOne = ModelAssociation.hasOne(associatedWith: Comment.keys.post, targetNames: ["postID"])
guard case .hasOne(let fieldName, let target) = hasOne else {
guard case .hasOne(let fieldName, let fieldNames, let target) = hasOne else {
XCTFail("Should create hasOne association")
return
}
XCTAssertEqual(fieldName, Comment.keys.post.stringValue)
XCTAssertEqual(fieldNames, [])
XCTAssertEqual(target, ["postID"])
}

func testHasOneWithCodingKeysWithAssociatedFields() {
let hasOne = ModelAssociation.hasOne(associatedFields: [Comment.keys.post])
guard case .hasOne(let fieldName, let fieldNames, let target) = hasOne else {
XCTFail("Should create hasOne association")
return
}
XCTAssertEqual(fieldName, nil)
XCTAssertEqual(fieldNames, ["post"])
XCTAssertEqual(target, [])
}

func testBelongsToWithTargetName() {
let belongsTo = ModelAssociation.belongsTo(targetName: "postID")
guard case .belongsTo(let fieldName, let target) = belongsTo else {
Expand Down

0 comments on commit e886cf0

Please sign in to comment.