Easy to Use, Read, Extensible, Flexible Validation Checker
MIT License
Easy to Use, Read, Extensible, Flexible Validation Checker.
It can use without Rx.
RxValidator
is written in Swift 4. Compatible with iOS 8.0+
RxValidator is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'RxValidator'
You just use like this:
//without Rx
Validate.to(TargetValue)
.validate(condition)
...
.validate(condition)
.asObservable() or .check()
//with Rx
observable
.validate(condition)
...
.validate(condition)
.subscribe(...)
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.check()
// result -> RxValidatorResult.valid
//multiple condition
Validate.to("[email protected]")
.validate(StringShouldNotBeEmpty())
.validate(StringIsNotOverflowThen(maxLength: 50))
.validate(StringShouldBeMatch("[a-z]+@[a-z]+\\.[a-z]+"))
.check()
// result -> RxValidatorResult.valid
let targetDate: Date //2018-05-05
let sameTargetDate: Date
let afterTargetDate: Date
let beforeTargetDate: Date
Validate.to(Date())
.validate(.shouldEqualTo(date: sameTargetDate)) //(1)
.validate(.shouldAfterOrSameThen(date: sameTargetDate)) //(2)
.validate(.shouldBeforeOrSameThen(date: sameTargetDate)) //(3)
.validate(.shouldBeforeOrSameThen(date: afterTargetDate)) //(4)
.validate(.shouldBeforeThen(date: afterTargetDate)) //(5)
.validate(.shouldAfterOrSameThen(date: beforeTargetDate)) //(6)
.validate(.shouldAfterThen(date: beforeTargetDate)) //(7)
.check()
// check() result
// valid result -> RxValidatorResult.valid
// (1) not valid -> RxValidatorResult.notEqualDate
// (2) not valid -> RxValidatorResult.notAfterDate
// (3) not valid -> RxValidatorResult.notBeforeDate
// (4) not valid -> RxValidatorResult.notBeforeDate
// (5) not valid -> RxValidatorResult.notBeforeDate
// (6) not valid -> RxValidatorResult.notAfterDate
// (7) not valid -> RxValidatorResult.notAfterDate
Validate.to(2)
.validate(NumberShouldBeEven())
.check()
//.valid
Validate.to(1)
.validate(NumberShouldBeEven())
.check()
//.notEvenNumber
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print("word is not empty")
})
.disposed(by: disposeBag)
Validate.to("word is not empty")
.validate(StringShouldNotBeEmpty())
.asObservable()
.map { $0 + "!!" }
.bind(to: anotherObservableBinder)
.disposed(by: disposeBag)
//Multiple condition
Validate.to("[email protected]")
.validate(StringShouldNotBeEmpty()) //(1)
.validate(StringIsNotOverflowThen(maxLength: 50)) //(2)
.validate(StringShouldBeMatch("[a-z]+@[a-z]+\\.[a-z]+")) //(3)
.asObservable()
.subscribe(onNext: { value in
print(value)
//print("[email protected]")
},
onError: { error in
let validError = RxValidatorResult.determine(error: error)
// (1) validError -> RxValidatorResult.stringIsEmpty
// (2) validError -> RxValidatorResult.stringIsOverflow
// (3) validError -> RxValidatorResult.stringIsNotMatch
})
.disposed(by: disposeBag)
Validate.to(2)
.validate(NumberShouldBeEven())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print(2)
})
.disposed(by: disposeBag)
Validate.to(1)
.validate(NumberShouldBeEven())
.asObservable()
.subscribe(onNext: { value in
print(value)
//print(1)
},
onError: { error in
let validError = RxValidatorResult.determine(error: error)
//validError -> RxValidatorResult.notEvenNumber
})
.disposed(by: disposeBag)
let targetDate: Date //2018-05-05
let sameTargetDate: Date
let afterTargetDate: Date
let beforeTargetDate: Date
Validate.to(Date())
.validate(.shouldEqualTo(date: sameTargetDate)) //(1)
.validate(.shouldAfterOrSameThen(date: sameTargetDate)) //(2)
.validate(.shouldBeforeOrSameThen(date: sameTargetDate)) //(3)
.validate(.shouldBeforeOrSameThen(date: afterTargetDate)) //(4)
.validate(.shouldBeforeThen(date: afterTargetDate)) //(5)
.validate(.shouldAfterOrSameThen(date: beforeTargetDate)) //(6)
.validate(.shouldAfterThen(date: beforeTargetDate)) //(7)
.asObservable()
.subscribe(onNext: { value in
print(value) //print("2018-05-05")
}, onError: { error in
let validError = RxValidatorResult.determine(error: error)
// (1) validError -> RxValidatorResult.notEqualDate
// (2) validError -> RxValidatorResult.notAfterDate
// (3) validError -> RxValidatorResult.notBeforeDate
// (4) validError -> RxValidatorResult.notBeforeDate
// (5) validError -> RxValidatorResult.notBeforeDate
// (6) validError -> RxValidatorResult.notAfterDate
// (7) validError -> RxValidatorResult.notAfterDate
})
.disposed(by: disposeBag)
textField.rx.text
.filterNil()
.validate(StringIsAlwaysPass())
.subscribe(onNext: { (text) in
print(text)
})
.disposed(by: disposeBag)
let text = PublishSubject<String>()
text
.validate(StringIsAlwaysPass())
.subscribe(onNext: { (text) in
print(text)
})
.disposed(by: disposeBag)
Validate.to("swift")
.validate({ $0 == "objc" })
.check()
Validate.to(7)
.validate({ $0 > 10 })
.check()
Validate.to(Date())
.validate({ !$0.isToday })
.check()
Validate.to("swift")
.validate({ $0 == "objc" }, message: "This is not swift")
.check()
Validate.to(7)
.validate({ $0 > 10 }, message: "Number is too small.")
.check()
Validate.to(Date())
.validate({ !$0.isToday }, message: "It is today!!")
.check()
enum RxValidatorResult
case notValid
case notValidWithMessage(message: String)
case notValidWithCode(code: Int)
case undefinedError
case stringIsOverflow
case stringIsEmpty
case stringIsNotMatch
case notEvenNumber
case invalidateDateTerm
case notBeforeDate
case notAfterDate
case notEqualDate
func mutate(action: Action) -> Observable<Mutation> {
....
case let .changeTitle(title):
return Validate.to(title)
.validate(StringIsNotOverflowThen(maxLength: TITLE_MAX_LENGTH))
.asObservable()
.flatMap { Observable<Mutation>.just(.updateTitle(title: $0)) }
.catchError({ (error) -> Observable<Mutation> in
let validError = ValidationTargetErrorType.determine(error: error)
return Observable<Mutation>.just(.setTitleValidateError(validError, title))
})
....
//String
StringShouldNotBeEmpty()
StringIsNotOverflowThen(maxLength: Int)
StringShouldBeMatch("regex string")
//Int
NumberShouldBeEven()
//Date
DateValidatorType.shouldEqualTo(Date)
DateValidatorType.shouldBeforeThen(Date)
DateValidatorType.shouldBeforeOrSameThen(Date)
DateValidatorType.shouldAfterThen(Date)
DateValidatorType.shouldAfterOrSameThen(Date)
DateValidatorType.shouldBeCloseDates(date: Date, termOfDays: Int)
//String Type
class MyCustomStringValidationRule: StringValidatorType {
func validate(_ value: String) throws {
if {notValidCondition} {
throw RxValidatorResult.notValidate(code: 999) //'code' must be defined your self.
}
}
}
//Int Type
class MyCustomIntValidationRule: IntValidatorType {
func validate(_ value: Int) throws {
if {notValidCondition} {
throw RxValidatorResult.notValidate(code: 999) //'code' must be defined your self.
}
}
}