···
On May 25, 2004, at 8:04 AM, Florian Weber wrote:
hi!
im trying to define a set of rules with ruby, however i cant find a
more
ruby-like way to do so…
instead of doing something like
my_set.add(NotNamedRule(“orange”).new)
my_set.add(HasPropertyRule(“color”).new)
my_set.add(OrRule(HasPropertyRule(“size”).new,
HasPropertyRule(“weight”).new))
(i know this is a horrible example. excuse the awful ‘design’. its
justs to illustrate
what i not wanna have ; )
i wanna do something like
my_set.rules = !name(“orange”) && hasProperty(“color”) &&
(hasProperty(“size”) || hasProperty(“weight”))
can anybody think of a nice way to do this?
file: dogrules.rb
class Dog
attr_reader :age, :breed, :name
def initialize(breed, age, name)
@breed, @age, @name = breed, age, name
end
end
class Rule
def initialize(rulename, *args)
@rulename, @args = rulename, args
end
def ===(other)
if other.kind_of? Dog
case @rulename
when :breed_is
@args[0] == other.breed
when :age_is
@args[0] == other.age
when :name_is_one_of
@args.any?{|a| a == other.name }
end
end
end
compare with or: rule1 | rule2
def |(other)
Ruleset.new(self, :or, other)
end
compare with and: rule1 & rule2
def &(other)
Ruleset.new(self, :and, other)
end
negate this rule: rule1.not
def not
Ruleset.new(self, :not)
end
end
class Ruleset < Rule
def initialize(one, op, two = nil)
@one, @op, @two = one, op, two
end
def ===(other)
case @op
when :or
@one === other or @two === other
when :and
@one === other and @two === other
when :not
not @one === other
end
end
end
dog1 = Dog.new(“black lab”, 3, “Rufus”)
dog2 = Dog.new(“beagle”, 2, “Bowser”)
dog3 = Dog.new(“black lab”, 4, “Blackie”)
rule1 = Rule.new(:breed_is, “black lab”)
rule2 = Rule.new(:name_is_one_of, “Bowser”, “Blackie”)
[dog1, dog2, dog3].map{|dog| rule1 === dog }
#=> [true, false, true]
[dog1, dog2, dog3].map{|dog| rule2 === dog }
#=> [false, true, true]
[dog1, dog2, dog3].map{|dog| (rule1 & rule2) === dog }
#=> [false, false, true]
HTH,
Mark