Giter Club home page Giter Club logo

rxvalidatorextended's Introduction

License Platform Swift Version Build Status codecov.io

RxValidator

Easy to Use, Read, Extensible, Flexible Validation Checker.

It can use without Rx.

Requirements

RxValidator is written in Swift 4. Compatible with iOS 8.0+

Installation

CocoaPods

RxValidator is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'RxValidator'

At a Glance

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(...)
    

Usage

String

	
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

Date

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

Int

Validate.to(2)
    .validate(NumberShouldBeEven())
    .check()
    //.valid
    
Validate.to(1)
    .validate(NumberShouldBeEven())
    .check()
    //.notEvenNumber

Working with RxSwift

String

	
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)
		

Int

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)

Date

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)

Chaining from Observable

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)

Instant Condition Validation

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()

ResultType

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

Working with ReactorKit (http://reactorkit.io)

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))
    })

....

Supported Validation Rules

//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)

Make custom ValidationRule like this:

//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.  
        }
    }
}

I want to be...

  • More Built-in Validation Rules. (Help me. Welcome to PR.)
  • Support More Type (Array, Float, Double, etc)
  • More Flexible Code via Generics.

rxvalidatorextended's People

Contributors

bataevvlad avatar cruisediary avatar kawoou avatar vbmania avatar wanbok avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.