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 request body creator non-default implementations getting hammered by compiler #1450

Merged
merged 4 commits into from
Oct 16, 2020

Conversation

designatednerd
Copy link
Contributor

@designatednerd designatednerd commented Oct 15, 2020

Addresses #1444. Note that this will be a breaking change.

So I seriously had to rewatch this bit of my own talk about this to figure out why this hadn't twigged on me earlier: I was expecting this to be like the sayHi method in that example, where because it's declared in the protocol, the compiler uses the lowest level of implementation rather than going to to the default implementation. Instead, it's behaving like the askHowAreYou method, which is not defined in the implementation, and which is defaulting to the protocol's default implementation.

The test we had previously validated that things worked when called directly, but not when called indirectly: When I made the changes to the test in this PR, it immediately started failing, so that definitely meant that we were closer to the askHowAreYou situation.

As far as I can tell, this is some weird combination of circumstances in terms of what we were doing with default values on the default argument vs. the implementation in the test. I suspect that because it looked like we were making the same call, we thought we were. But due to the default implementation's default values, we were actually calling two totally different methods on the two tests, and that only revealed itself when called indirectly.

SO. Because I know there are existing implementations that rely on just passing things straight through to what was the default implementation, I've updated that to just be called defaultRequestBody so it can be called from other implementations of RequestBodyCreator(you can see an example in how I set up the updated ApolloRequestCreator). This also allows you to grab the default and modify it instead of having to redo the whole thing yourself. UPDATE: I realized it was much cleaner to just remove the default values from the default implementation, so I did that instead.

Sources/Apollo/RequestBodyCreator.swift Outdated Show resolved Hide resolved
Sources/Apollo/RequestBodyCreator.swift Outdated Show resolved Hide resolved
@@ -69,7 +69,10 @@ open class UploadRequest<Operation: GraphQLOperation>: HTTPRequest<Operation> {
// Make sure all fields for files are set to null, or the server won't look
// for the files in the rest of the form data
let fieldsForFiles = Set(files.map { $0.fieldName }).sorted()
var fields = self.requestBodyCreator.requestBody(for: operation, sendOperationIdentifiers: shouldSendOperationID)
var fields = self.requestBodyCreator.requestBody(for: operation,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to not change this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to change due to the removal of the default values for these parameters

Copy link

@wangjiejacques wangjiejacques Oct 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @designatednerd , although the default values for these parameters has been removed, but I think it's a good idea to add a new extension method like this:

/// Don't override this method, override `requestBody(operation, false, true, false)` 
extension RequestBodyCreator {
    public func requestBody<Operation: GraphQLOperation>(for operation: Operation) {
        requestBody(operation, false, true, false)
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll consider that, but I am concerned that would run a significant risk of reintroducing this same problem.

@@ -270,7 +270,10 @@ public class WebSocketTransport {
}

func sendHelper<Operation: GraphQLOperation>(operation: Operation, resultHandler: @escaping (_ result: Result<JSONObject, Error>) -> Void) -> String? {
let body = requestBodyCreator.requestBody(for: operation, sendOperationIdentifiers: self.sendOperationIdentifiers)
let body = requestBodyCreator.requestBody(for: operation,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not change this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to change due to the removal of the default values for these parameters

@designatednerd
Copy link
Contributor Author

Took a second pass after a day and discovered the real best way to handle this was to just ditch the default values in the default implementation. Made a couple tests dumber, but I think from a standpoint of not breaking as hard, this is better.

Still technically breaking since I removed the default values, though.

@designatednerd designatednerd merged commit cf53770 into main Oct 16, 2020
@designatednerd designatednerd deleted the fix/protocol-default-implementation branch October 16, 2020 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants