jruizgit / rules

Durable Rules Engine
MIT License
1.16k stars 206 forks source link

context state is not evaluated in rule #75

Open mawilmsen opened 7 years ago

mawilmsen commented 7 years ago

Hi,

I'm trying to use the context to apply some filtering on my rules, i.e. only call my "callme" action when the "doit" flag is set in the state of the current sid:

with ruleset('datapoint'):
    @when_all(m.category == 'foo', c.s.doit)
    def callme(c):
        print 'context state is', c.s

    @when_start
    def start(host):
        host.patch_state('datapoint', {'sid': 'foobar1', 'doit': True})
        host.patch_state('datapoint', {'sid': 'foobar2', 'doit': False})

        host.assert_fact('datapoint', {'id': 1, 'category': 'foo', 'sid': 'foobar1'})
        host.assert_fact('datapoint', {'id': 2, 'category': 'foo', 'sid': 'foobar2'})

Now, regardless of the actual sid, the action is executed in both cases, although the print statement inside the action shows the correct context state:

context state is {u'doit': True, u'sid': u'foobar1'}
context state is {u'doit': False, u'sid': u'foobar2'}

Seems the state attributes inside the rule definition (c.s.doit) are not evaluated, or am I misunderstanding the concept of the state? I also tried c.s.ref_id('foobar2').doit, but the action is still being called.

Appreciate any help on this.

jruizgit commented 7 years ago

Hi, the syntax for context state evaluation is not very intuitive. m represents a rule on a fact or an event posted s represents rule on an event on context state saved. Everytime the state context is saved, an event is posted. For example:

with ruleset('datapoint'):
    @when_all(c.first << s.doit == True,
              c.second << m.category == 'foo') 
    def callme(c):
        print 'callme context state is', c.s
        print 'callme first message is ', c.first
        print 'callme second message is ', c.second
        c.s.doit = False

    @when_all(c.first << s.doit == False,
              c.second << m.category == 'foo')
    def dont_callme(c):
        print 'dont_callme context state is', c.s
        print 'dont_callme first message is ', c.first
        print 'dont_callme second message is ', c.second
        c.s.doit = True

    @when_start
    def start(host):
        host.patch_state('datapoint', {'sid': 'foobar1', 'doit': True})
        host.assert_fact('datapoint', {'id': 1, 'category': 'foo', 'sid': 'foobar1'})

run_all()