jruizgit / rules

Durable Rules Engine
MIT License
1.14k stars 207 forks source link

Is it possible to specify operators dynamically? #337

Open dragonchoi opened 4 years ago

dragonchoi commented 4 years ago

Thank you for developing good open source.

I am wondering if it is possible to dynamically assign an operator like the code below.

[INPUT]

post('array',
        {'conditions': [
                [
                        {'value' : 2, 'operator': '==', 'device_value' : 1},
                        {'value' : 2, 'operator': '!=', 'device_value' : 2}
                ],
                [
                        {'value': 2, 'operator': '!=', 'device_value': 2},
                        {'value': 2, 'operator': '==', 'device_value': 2}
                ]
        ]}
)

[RULESET]

with ruleset('array'):
        @when_all(m.conditions.allItems(item.allItems(value **<dynamic operator**> device_value )))
        def test_rule(c):
                print("rule pass")

Thank you.

mrryanjohnston commented 4 years ago

@dragonchoi I don't think this is handled by durable_rules natively. However, I got something working that allowed me to check when a timer with a dynamic name timed out with something like this:

require 'durable'

module Durable
  class Ruleset
    def dynamic_timer_times_out
      all(c.timer = +m.name,
          c.base = Expression.new(:$m, "$timerName") == timer.name,
          c.timeout = Expression.new(:$m, "$time") >= Arithmetic.new(:base, "$baseTime")
      )
    end
  end
end

Durable.ruleset :timers do
  when_all(c.timer = (+m.event) & (m.event == 'start')) do
    start_timer timer.name, timer.length
  end

  when_all(dynamic_timer_times_out) do
    puts timer.name
  end
end

Durable.assert :timers, { event: 'start', name: 'Foo!', length: 1 }
Durable.assert :timers, { event: 'start', name: 'Bar!', length: 4 }
Durable.assert :timers, { event: 'start', name: 'Bat!', length: 3 }
Durable.assert :timers, { event: 'start', name: 'Baz', length: 2 }

sleep(4)

This outputs:

Foo!
Baz
Bat!
Bar!