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

Validation Error support #2

Closed
myurieff opened this issue Jul 4, 2019 · 4 comments
Closed

Validation Error support #2

myurieff opened this issue Jul 4, 2019 · 4 comments
Labels
enhancement New feature or request

Comments

@myurieff
Copy link

myurieff commented Jul 4, 2019

Hello Sven.
Wonderful project, well done!

Motivation

I believe it would be a nice addition to implement support for reporting validation errors. It can be helpful, for example, when you want to display a related error message to the user.

Solution

I played around with the project in a fork. I would love to implement the changes myself and submit a PR, but wanted to first do a proposal and open a discussion.

There are a couple of ways to do it. What first comes to my mind would be this:

  • Let's say that we have a special struct to report our errors:
public struct ValidationError: Error {
    let localizedMessage: String
    ...
}
  • The validation closure could return a Result<Value, ValidationError>, instead of a Bool.

  • The property wrapper could include a validationError optional property that receives values upon validation and gets set to nil when restore() is called.

  • When using, we would be able to check for a validationError and if there isn't any, we can go ahead and use the value.

Here's a rough example:

public extension Validation where Value == String {

    static var isValidPassword: Validation {
        return .init { (value) -> Result<String, ValidationError> in
            if value.count < 6 {
                return .failure(ValidationError(localizedMessage: "Password is too short. Minimum character count is 6."))
            }

            /* Additional checks

                ...

            */

            return .success(value)
        }
    }

}
if let errorMessage = $passwordInput.validationError?.localizedMessage {
    UserNotification.displayError(message: errorMessage)
    return 
}

// Safe to continue and use the passwordInput string

Additional Remarks

This feature would require quite some changes, but all of them would be internal to the API, meaning that the users of it won't have to change anything when using the default provided validations. However, their custom ones will have to be rewritten to return Results, instead of Bools.

All of this is a result of a small pre-lunch brainstorm. I'm sure there is a way to improve it 😄 Let me know what you think :)

@SvenTiigi
Copy link
Owner

SvenTiigi commented Jul 4, 2019

Hey @myurieff,

Thank you for your detailed proposal good job 👍

Your proposed solution looks great and is an perfect enhancement for the Validation struct so please feel free to open up a PR on the feature branch error-propagation to get things started.

I was lately thinking the same in how to improve the error propagation for ValidatedPropertyKit. Maybe another API improvement would be to allow specifying the Error type via the Result type directly on the property declaration level. For example:

@Validated(.myValidation)
var property: Result<String, MyValidationError>

To enable this kind of API a little bit more work has to be done and maybe it would be better to add this API as another Property Wrapper named @StrictValidated to allow using it beside the current @Validated Property Wrapper.

@SvenTiigi SvenTiigi added the enhancement New feature or request label Jul 4, 2019
@SvenTiigi
Copy link
Owner

Hey @myurieff,

the latest release 0.0.2 now contains the option to access the ValidationError.

Please feel free to open up a new issue or PR for further feedback 👌

@ge-org
Copy link

ge-org commented Aug 16, 2019

Hi,

sorry for commenting on this old issue :/
Are you still pursuing the idea of specifying custom error types? Currently it's impossible to find out in code which validation failed. Each validation uses the ValidationError and it only provides a string description.

It would be great to have a different kind of error for each validation rule so we could switch over the error to determine which rule (or rules) failed.

switch $username.validationError {
  case .nonEmpty: handleEmptyUsername()
  case let .range(expectedRange): handleInvalidUsernameLength(expectedRange)
  case .none: print("all good")
}

Cheers, Georg

@sustainjane98
Copy link

Has this been removed in a newer version? Cannot find the errorMessage Property on the Wrapper anymore? I don't know what to do with multiple validations and how to distinguish them from another to show different messages for each of them. Any solution to this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants