Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(v1): CPK has-many has-one associatedFields #2734

Merged
merged 1 commit into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ 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 hasOne(associatedFieldName: String?, targetNames: [String])
case hasMany(associatedFieldName: String?, associatedFieldNames: [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 @@ -98,18 +98,25 @@ 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:)")
public static func hasOne(associatedWith: CodingKey?, targetName: String? = nil) -> ModelAssociation {
@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 @@ -234,13 +241,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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,19 @@ 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,
associatedFields: associatedKeys))
}

public static func hasOne(_ key: CodingKey,
is nullability: ModelFieldNullability = .required,
isReadOnly: Bool = false,
Expand All @@ -267,6 +280,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 @@ -207,7 +207,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 @@ -92,7 +92,7 @@ class DataStoreObserveQueryOperationTests: XCTestCase {
let secondSnapshot = expectation(description: "second query snapshots")
let thirdSnapshot = expectation(description: "third query snapshot")
thirdSnapshot.isInverted = true

var querySnapshots = [DataStoreQuerySnapshot<Post>]()
let dispatchedModelSyncedEvent = AtomicValue(initialValue: false)
let operation = AWSDataStoreObserveQueryOperation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -37,7 +37,7 @@ class ModelFieldAssociationTests: XCTestCase {

func testHasOneWithCodingKeys() {
let hasOne = ModelAssociation.hasOne(associatedWith: Comment.keys.post, targetName: nil)
guard case .hasOne(let fieldName, let target) = hasOne else {
guard case .hasOne(let fieldName, _, let target) = hasOne else {
XCTFail("Should create hasOne association")
return
}
Expand All @@ -47,7 +47,7 @@ class ModelFieldAssociationTests: XCTestCase {

func testHasOneWithCodingKeysWithTargetName() {
let hasOne = ModelAssociation.hasOne(associatedWith: Comment.keys.post, targetName: "postID")
guard case .hasOne(let fieldName, let target) = hasOne else {
guard case .hasOne(let fieldName, _, let target) = hasOne else {
XCTFail("Should create hasOne association")
return
}
Expand Down