The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Rule::Engine - A Rule Engine

DESCRIPTION

Rule::Engine is a system for creating sets of rules (RuleSets) and executing them against a list of objects.

SYNOPSIS

    use Rule::Engine::Filter;
    use Rule::Engine::Rule;
    use Rule::Engine::RuleSet;
    use Rule::Engine::Session;

    my $sess = Rule::Engine::Session->new;
    $sess->set_environment('temperature', 65);

    # Make a ruleset
    my $rs = Rule::Engine::RuleSet->new(
        name => 'some-ruleset',
        filter => Rule::Engine::Filter->new(
            condition => sub {
                # Check something here.  Any object that returns true will
                # be kept. Args are $self, $session and the object
                my ($self, $sess, $obj);
                $obj->happy ? 1 : 0
            }
        )
    );

    # Make a rule to add to the set.  This rule's condition will be executed
    # for each object.  If it returns a true value then the action will be
    # executed for each object.
    my $rule = Rule::Engine::Rule->new(
        name => 'temperature',
        condition => sub {
            my ($self, $sess, $obj) = @_;
            return $obj->favorite_temp == $sess->get_environment('temperature');
        },
        action => sub {
            my ($self, $sess, $obj) = @_;
            $obj->happy(1);
        }
    );

    # Add the rule
    $rs->add_rule($rule);

    # Add the ruleset to the session
    $sess->add_ruleset($rs->name, $rs);

    # Execute the rule, getting back an arrayref of objects that passed the
    # filter after running through all the rules whose conditions were met
    my $results = $sess->execute('some-ruleset', \@list_of_objects);

CONCEPTS

Rules

Rules are made of a condition and an action. If the condition evaluates to true for a given object, then the action is executed.

        my $rule = Rule::Engine::Rule->new(
            name => 'check_score',
            condition => sub {
                my ($self, $sess, $obj) = @_;
                        # Test the score
                return $obj->score >= 59;
            },
            action => sub {
                my ($self, $sess, $obj) = @_;
                        # Passing score!
                $obj->pass(1);
            }
        );

Conditions and actions are executed individually for each object that is passed into the RuleSet.

RuleSets

RuleSets are collections of rules – executed in order – with an optional filter that removes objects that match (or don't match) a certain criteria after all the rules have been evaluated.

        my $rs = Rule::Engine::RuleSet->new(
            name => 'some-ruleset',
                # Completely optional filter
            filter => Rule::Engine::Filter->new(
                condition => sub {
                    # Check something here.  Any object that returns true will
                    # be kept.
                    $_[1]->is_something ? 1 : 0
                }
            )
        );

        $rs->add_rule(...);
        $rs->add_rule(...);

        my $results = $rs->execute(\@objects);

The above example has two rules and a filter. The filter removes any objects from the results after the rules have been executed. Since each rule might alter the object, the filter has a chance at the end to limit the returned objects to just those that have met certain criteria. This might be useful to determine which students have passed an example, which items in a cart need to be removed or which customers have the appropriate attributes for a promotion.

Session

A session is a period of interaction with Rule::Engine. The environment provides a collection of possible RuleSets and an environment hash.

NOTES

Filtered and Unfiltered

There are two common use-cases for a RuleSet: filtered and unfiltered. Filtered RuleSets are primarily used for binary problem. If you need to evaluate some rules and then eliminate some items, this is how you do it. This seems (to me at least) fairly obvious. The other option, less so.

Unfiltered RuleSets don't eliminate anyone and in my uses are often not used with multiple input objects. A great example of this is calculating a credit limit for a credit application. There's nothing to eliminate, in this case. We want to first decide if the customer is eligible for credit and then, based on various attributes, decide how much credit to give them. A single Application object may be passed in and attributes tested and set. If the credit score is too low, then the limit may be set to 0. Afterward, there's no reason for a filter. We just want to know what the value of Account-limit> turned out to be.

The point of this documentation blurb is to illustrate that Rule::Engine is useful in terms of deciding how to do something, not just which objects to do something to.

AUTHOR

Cory G Watson, <gphat at cpan.org>

ACKNOWLEDGEMENTS

COPYRIGHT & LICENSE

Copyright 2010 Cory G Watson.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 91:

Non-ASCII character seen before =encoding in '–'. Assuming UTF-8

Around line 148:

=back without =over