Skip to content
/ brex Public

define, compose, and evaluate your business rules in Elixir

License

Notifications You must be signed in to change notification settings

alexocode/brex

Repository files navigation

Brex

CI Coverage Status Hexdocs.pm Hex.pm Hex.pm Downloads

A Specification Pattern implementation in Elixir.

Using brex you can easily

  • define
  • compose and
  • evaluate

business rules to dynamically drive the flow of your application.

Motiviation

Brex was built to allow you to define and compose rules to evaluate them later. This enables you to build your rules from some kind of configuration, be it a database, a CSV or JSON or anything else.

Maybe you want to allow your customer to create dynamic rules for sending out emails or push notifications? Or you want to decide on the type of event to trigger based on incoming data? Or you think bigger and want to create some kind of flow chart interface?

Whatever your particular use-case, Brex has you covered when it comes to composition of rules.

Basics

The lowest building stone of Brex is a rule. A rule can have many shapes, for example this is a rule:

&is_list/1

This is a rule too:

Brex.all([&is_list/1, &(length(&1) > 0)])

Or this:

defmodule MyRule do
  @behaviour Brex.Rule

  @impl true
  def evaluate(:foo), do: true
  def evaluate(:bar), do: false
end

Also this:

defmodule MyStruct do
  use Brex.Rule.Struct

  defstruct [:foo]

  def evaluate(%{foo: foo}, value) do
    foo == value
  end
end

Enough talk about defining rules, how can I evaluate them?

Well great that you ask, that's simple too!

iex> Brex.satisfies? MyRule, :foo
true

As you can see, Brex is flexible and easy to use. All of this is based on the Brex.Rule.Evaluable protocol, if you're really interested, take a look at Brex.Rule which talks about the possible rule types a little bit more.

Operators

Also, as you might have noticed, I used an all/1 function in the examples above. This is the compose part of Brex: it allows you to link rules using boolean logic.

It currently supports:

  • all
  • any
  • none

I think the names speak for themself.

You can define your own operators, if you're interested then take a look at the Brex.Operator module.

Installation

Simply add brex to your list of dependencies in your mix.exs:

def deps do
  [
    {:brex, "~> 0.1.0"}
  ]
end

Configuration

Right now, there is no need for any kind of configuration in Brex. In case you see some need for it, please open an issue.