Skip to content

Commit

Permalink
Added when and setValidator
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobaraujo7 committed Aug 25, 2024
1 parent 48d1f73 commit 37ae04a
Show file tree
Hide file tree
Showing 15 changed files with 395 additions and 139 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.0.7

* Added `when` and `setValidator`

## 0.0.5

* Added must and mustWith
Expand Down
116 changes: 108 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ void main() {
final user = UserModel(email: '[email protected]', password: 'Passw0rd!', age: 25);
final validator = UserValidator();
final errors = validator.validate(user);
final result = validator.validate(user);
if (errors.isEmpty) {
if (result.isValid) {
print('User is valid');
} else {
print('Validation errors: \${errors.map((e) => e.message).join(', ')}');
print('Validation errors: \${result.errors.map((e) => e.message).join(', ')}');
}
}
```
Expand Down Expand Up @@ -169,14 +169,114 @@ You can apply CascadeMode to your validation chain using the cascaded method:
.mustHaveSpecialCharacter()
```

## When condition

Adds a conditional execution rule for the validation logic based on the given [condition].

The `when` method allows you to specify a condition that must be met for the validation rules
within this builder to be executed. If the condition is not met, the validation rules areskipped,
and the property is considered valid by default.

This is particularly useful for scenarios where certain validation rules should only apply
under specific circumstances, such as when a certain property is set to a particular value.

[condition] is a function that takes the entire entity and returns a boolean indicating whether
the validation rules should be applied.

Example:

```dart
ruleFor((user) => user.phoneNumber, key: 'phoneNumber')
.when((user) => user.requiresPhoneNumber)
.must((value) => value.isNotEmpty, 'Phone number is required', 'phone_required')
.must((value) => value.length == 10, 'Phone number must be 10 digits', 'phone_length');
```

In the example above, the phone number validation rules are only applied if the user's`requiresPhoneNumber`
property is true. If the condition is false, the phone number field will be considered valid,and the
associated rules will not be executed.

## Complex Validations

When working with complex models that contain nested objects, it’s often necessary to apply validation rules not only to the parent model but also to its nested properties. The `setValidator` method allows you to integrate a nested `LucidValidator` within another validator, enabling a modular and scalable approach to validation.

See this example:
```dart
// Models
class Customer {
String name;
Address address;
Customer({
required this.name,
required this.address,
});
}
class Address {
String country;
String postcode;
Address({
required this.country,
required this.postcode,
});
}
```

Now, we can create two validators, `CustomerValidator` and `AddressValidator`.
Use `setValidator` to integrate `AddressValidor` into `CustomerValidator`;

```dart
class AddressValidator extends LucidValidator<Address> {
AddressValidator() {
ruleFor((address) => address.country, key: 'country') //
.notEmpty();
ruleFor((address) => address.postcode, key: 'postcode') //
.notEmpty();
}
}
class CustomerValidator extends LucidValidator<Customer> {
final addressValidator = AddressValidator();
CustomerValidator() {
ruleFor((customer) => customer.name, key: 'name') //
.notEmpty();
ruleFor((customer) => customer.address, key: 'address') //
.setValidator(addressValidator);
}
}
```

After that, execute a validation normaly:

```dart
var customer = Customer(
name: 'John Doe',
address: Address(
country: 'Brazil',
postcode: '12345-678',
),
);
final validator = CustomerValidator();
var result = validator.validate(customer);
expect(result.isValid, isTrue);
```


## Creating Custom Rules

You can easily extend the functionality of `LucidValidation` by creating your own custom rules using `extensions`. Here’s an example of how to create a validation for phone numbers:
You can easily extend the functionality of `LucidValidator` by creating your own custom rules using `extensions`. Here’s an example of how to create a validation for phone numbers:

```dart
extension CustomValidPhoneValidator on LucidValidationBuilder<String, dynamic> {
LucidValidationBuilder<String> customValidPhone({String message = 'Invalid phone number format'}) {
extension CustomValidPhoneValidator on SimpleValidationBuilder<String> {
SimpleValidationBuilder<String> customValidPhone({String message = 'Invalid phone number format'}) {
return matchesPattern(
r'^\(?(\d{2})\)?\s?9?\d{4}-?\d{4}\$',
message,
Expand All @@ -185,8 +285,8 @@ extension CustomValidPhoneValidator on LucidValidationBuilder<String, dynamic> {
}
}
extension CustomValidPasswordValidator on LucidValidationBuilder<String, dynamic> {
LucidValidationBuilder<String> customValidPassword() {
extension CustomValidPasswordValidator on SimpleValidationBuilder<String> {
SimpleValidationBuilder<String> customValidPassword() {
return notEmpty()
.minLength(8)
.mustHaveLowercase()
Expand Down
14 changes: 9 additions & 5 deletions example/lib/domain/validations/extensions.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:lucid_validation/lucid_validation.dart';

extension CustomValidPasswordValidator on LucidValidationBuilder<String, dynamic> {
LucidValidationBuilder<String, dynamic> customValidPassword() {
extension CustomValidPasswordValidator on SimpleValidationBuilder<String> {
SimpleValidationBuilder<String> customValidPassword() {
return notEmpty() //
.minLength(5)
.mustHaveLowercase()
Expand All @@ -11,8 +11,12 @@ extension CustomValidPasswordValidator on LucidValidationBuilder<String, dynamic
}
}

extension CustomValidPhoneValidator on LucidValidationBuilder<String, dynamic> {
LucidValidationBuilder<String, dynamic> customValidPhone(String message) {
return must((value) => RegExp(r'^\(?(\d{2})\)?\s?9?\d{4}-?\d{4}$').hasMatch(value), message, 'invalid_phone');
extension CustomValidPhoneValidator on SimpleValidationBuilder<String> {
SimpleValidationBuilder<String> customValidPhone(String message) {
return matchesPattern(
r'^\(?(\d{2})\)?\s?9?\d{4}-?\d{4}$',
message: message,
code: 'invalid_phone',
);
}
}
10 changes: 5 additions & 5 deletions example/lib/presentation/register_page/register_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ class _RegisterPageState extends State<RegisterPage> {
}

void signIn() {
final errors = validator.validate(registerParamDto);
final result = validator.validate(registerParamDto);

if (errors.isEmpty) {
if (result.isValid) {
/// call to api passing the parameter loginParamDto
ScaffoldMessenger.of(context).showSnackBar(sucessSnackBar());
} else {
ScaffoldMessenger.of(context).showSnackBar(failureSnackBar(errors.first.message));
ScaffoldMessenger.of(context).showSnackBar(failureSnackBar(result.errors.first.message));
}
}

Expand Down Expand Up @@ -104,10 +104,10 @@ class _RegisterPageState extends State<RegisterPage> {
ListenableBuilder(
listenable: registerParamDto,
builder: (context, child) {
final errors = validator.validate(registerParamDto);
final result = validator.validate(registerParamDto);

return ElevatedButton(
onPressed: errors.isEmpty ? signIn : null,
onPressed: result.isValid ? signIn : null,
child: const Text('Register'),
);
},
Expand Down
26 changes: 13 additions & 13 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.4"
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
Expand All @@ -113,7 +113,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.5"
version: "0.0.6"
matcher:
dependency: transitive
description:
Expand All @@ -126,18 +126,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.8.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.12.0"
version: "1.15.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -195,10 +195,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.2"
vector_math:
dependency: transitive
description:
Expand All @@ -211,10 +211,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.1"
version: "14.2.5"
sdks:
dart: ">=3.4.3 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
1 change: 1 addition & 0 deletions lib/lucid_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
///
library lucid_validation;

export 'src/lucid_validation_builder.dart';
export 'src/lucid_validator.dart';
export 'src/types/types.dart';
export 'src/validations/validations.dart';
Loading

0 comments on commit 37ae04a

Please sign in to comment.