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

Add example support. #10

Merged
merged 7 commits into from
Jun 14, 2017
Merged

Add example support. #10

merged 7 commits into from
Jun 14, 2017

Conversation

n8chur
Copy link
Collaborator

@n8chur n8chur commented May 31, 2017

  • Adds example support to schema properties.
  • Adds support for x-example on parameter definitions.
  • Adds an other(String) type to StringFormat.

- Adds `example` support to schema properties.
- Adds support for `x-example` on parameter definitions.
- Adds an `other(String)` type to `StringFormat`.
@n8chur n8chur requested a review from AttilaTheFun May 31, 2017 21:34
Copy link
Owner

@AttilaTheFun AttilaTheFun left a comment

Choose a reason for hiding this comment

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

I made some suggestions about how I think we could clean up StringFormat while adding the new functionality you suggested.

public enum StringFormat: String {
public enum StringFormat: RawRepresentable {

public typealias RawValue = String

/// Base64 encoded characters
case byte
Copy link
Owner

Choose a reason for hiding this comment

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

Let's add the following options, per the JSON Schema spec:

"date-time": Date representation, as defined by RFC 3339, section 5.6.
"email": Internet email address, see RFC 5322, section 3.4.1.
"hostname": Internet host name, see RFC 1034, section 3.1.
"ipv4": IPv4 address, according to dotted-quad ABNF syntax as defined in RFC 2673, section 3.2.
"ipv6": IPv6 address, as defined in RFC 2373, section 2.2.
"uri": A universal resource identifier (URI), according to RFC3986.

As well as our added byte, binary, url and other options.

@@ -1,6 +1,8 @@
import Foundation

public enum StringFormat: String {
public enum StringFormat: RawRepresentable {
Copy link
Owner

Choose a reason for hiding this comment

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

How about we move StringFormat into its own file, StringFormat.swift

}

guard
let aStringFormat = aStringOptionalFormat,
Copy link
Owner

Choose a reason for hiding this comment

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

How about anOptionalStringFormat

@AttilaTheFun
Copy link
Owner

Oh I don't know how it lost my comment, but I suggested defining a nested, private, RawStringFormat enum which is strongly-typed instead of defining a bunch of private static raw value strings @n8chur

}
}

private enum RawStringFormat: String {
Copy link
Owner

Choose a reason for hiding this comment

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

Looks Good :)

Copy link
Owner

@AttilaTheFun AttilaTheFun left a comment

Choose a reason for hiding this comment

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

Looks pretty good - just added a few more comments.

/// A universal resource identifier (URI), according to RFC3986.
case uri

public init(rawValue: RawValue) {
Copy link
Owner

Choose a reason for hiding this comment

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

Once you've typealiased RawValue = String, you can use String everywhere else in the type.


public var rawValue: RawValue {
switch self {
case .byte: return RawStringFormat.byte.rawValue
Copy link
Owner

Choose a reason for hiding this comment

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

How about making a private function that returns the raw string format optionally? E.g.:

private func rawStringFormat() -> RawStringFormat? {
    switch self {
    case .byte: return .byte
    case .binary: return .binary
    case .date: return .date
    case .dateTime: return .dateTime
    case .email: return .email
    case .hostname: return .hostname
    case .ipv4: return .ipv4
    case .ipv6: return .ipv6
    case .password: return .password
    case .uri: return .uri
    case .other: return nil
    }
}

public var rawValue: String {
    if let rawValue = self.rawStringValue() {
        return rawValue
    } else if case .other(let rawValue) = self {
        return rawValue
    } else {
        assertionFailure()
        return ""
    }
}

Copy link
Collaborator Author

@n8chur n8chur Jun 14, 2017

Choose a reason for hiding this comment

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

I had something similar at first, but ended up going with the approach found in this revision to avoid the fatalError() branch (which, although it should never be hit, needs to exist). I agree that it does clean up the rawValue implementation and makes the mapping easier to read, but I'm not sure that it's worth introducing the failure case for.

Would you prefer that I take the approach that you recommended or do you think avoiding the failure case is preferable? Do you have an alternate suggestion that doesn't involve a branch that results in a fatalError()?

Copy link
Owner

Choose a reason for hiding this comment

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

I mean, you can see that the assertion failure can never be hit here. The raw value will only be nil if self == .other, in which case the else if case will be hit. The assertion failure is to prevent someone from adding another case and not handling it in the future, and assertions don't trigger in prod builds.

return
}

self = rawStringFormat.stringFormat
Copy link
Owner

Choose a reason for hiding this comment

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

This function can be reduced to:

public init(rawValue: String) {
    self = RawStringFormat(rawValue: rawValue)?.stringFormat ?? .other(rawValue)
}


init(map: Map) throws {
name = try map.value("name")
location = try map.value("in")
description = try? map.value("description")
required = (try? map.value("required")) ?? false
example = try? map.value("x-example")
Copy link
Owner

Choose a reason for hiding this comment

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

Why is the field name x-example here but example in Metadata?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

example is not a documented key for parameter. "body" parameters can have a schema which could have an example, but non-"body" parameters do not have an example key. Here's a link to the spec where it discusses parameters.

In order to introduce this feature on all parameter types, I added support for x-example to allow specs utilizing the feature to remain valid Swagger OpenAPI 2.0 specs.

Copy link
Owner

Choose a reason for hiding this comment

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

Ok, sure. Thanks

@AttilaTheFun
Copy link
Owner

Also please rebase this off of master now that your other changes are merged. To prevent us from having repeated merge conflicts in our tests files, can we break up the tests into multiple files based on the subject they're testing?
E.g. AllOfTests.swift, ExampleTests.swift, BasicTests.swift ...

Copy link
Owner

@AttilaTheFun AttilaTheFun left a comment

Choose a reason for hiding this comment

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

Thanks so much for doing this! It looks great :)


init(map: Map) throws {
name = try map.value("name")
location = try map.value("in")
description = try? map.value("description")
required = (try? map.value("required")) ?? false
example = try? map.value("x-example")
Copy link
Owner

Choose a reason for hiding this comment

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

Ok, sure. Thanks

@n8chur n8chur merged commit 8713b2d into master Jun 14, 2017
@n8chur n8chur deleted the example branch June 14, 2017 20:06
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