-
Notifications
You must be signed in to change notification settings - Fork 68
RuleBase
When a command is invoked, its parameters can be subjected to business and validation rules. Business rules are generally considered to be rules that govern changing the state of data, or DTOs within the context of the Peasy framework.
Business rules cover a wide array of use cases. For example, you may want a business rule that states that new customers have to be at least 18 years old, or you may want to ensure that an item can't be deleted from a data store if it has been shipped.
You may also want authorization rules to allow or prohibit access to particular service commands. For example, administrators might be the only users that can insert or update product information.
The business rules engine is at the heart of the Peasy framework, and offers an easy way to create rules that are flexible, easy to consume, configure, reuse, maintain, and test, all through the usage of RuleBase.
Asynchronously executes the rule and sets the IsValid
status based on success or failure of the rule execution. If IsValid
is false
, the ErrorMessage
property will contain the error that describes how the validation failed.
To create a business rule, simply:
- Create a class that inherits from RuleBase.
- Override
OnValidateAsync
. - Invoke
Invalidate
if the rule fails validation.
public class CustomerAgeVerificationRule : RuleBase
{
private DateTime _birthDate;
public CustomerAgeVerificationRule(DateTime birthDate)
{
_birthDate = birthDate;
}
protected override Task OnValidateAsync()
{
if ((DateTime.Now.Year - _birthDate.Year) < 18)
{
Invalidate("New users must be at least 18 years of age");
}
return Task.CompletedTask;
}
}
The CustomerAgeVerificationRule simply checks that the supplied birth date is at least 18 years of age.
Here's an example writing the same rule using an alternate supported syntax:
public class CustomerAgeVerificationRule : RuleBase
{
private DateTime _birthDate;
public CustomerAgeVerificationRule(DateTime birthDate)
{
_birthDate = birthDate;
}
protected override Task OnValidateAsync()
{
return If(() => (DateTime.Now.Year - _birthDate.Year) < 18)
.ThenInvalidateWith("New users must be at least 18 years of age");
}
}
Rules can be passed any form of data from any data source imaginable. Often times, you'll want the rule itself to be responsible for obtaining data that it will use to determine validity.
Here's an example:
public class CanDeleteOrderItemRule : RuleBase
{
private int _itemId;
private IDataProxy<OrderItem, int> _orderItemDataProxy;
public CanDeleteOrderItemRule(int itemId, IDataProxy<OrderItem, int> orderItemDataProxy)
{
_itemId = itemId;
_orderItemDataProxy = orderItemDataProxy;
}
protected override async Task OnValidateAsync()
{
var orderItem = await _orderItemDataProxy.GetByIDAsync(_itemId);
if (orderItem.Status == STATUS.Shipped)
{
Invalidate("This item has been shipped and cannot be deleted");
}
}
}
Here is how we can easily test the CustomerAgeVerificationRule:
var invalidRule = await new CustomerAgeVerificationRule(DateTime.Now.AddYears(-17)).ExecuteAsync();
invalidRule.IsValid.ShouldBe(false);
invalidRule.ErrorMessage.ShouldBe("New users must be at least 18 years of age");
var validRule = await new CustomerAgeVerificationRule(DateTime.Now.AddYears(-30)).ExecuteAsync();
validRule.IsValid.ShouldBe(true);
validRule.ErrorMessage.ShouldBeNull();