class RubyTalk < Filter
+ to("ruby-talk@ruby-lang.org")
+ cc("ruby-talk@ruby-lang.org")
- from("common.troll@gifted.net")
end
class SelfBlog < Filter
+ to("selfblog@hobix.com")
+ subject("secretpassword")
def process(msg)
Blog.add_post(msg)
end
end
Young ones, see if you can figure out how it’s done before I hand you the actual raw sprinkles of meta magic dust. Specifically: (1) where are the rules getting stored? and (2) how are the operators actually implemented? Just have a think before the spoilers.
First, the Code
class Filter
class Rule
attr_accessor :field, :terms, :action
def initialize(f, *a)
@field = f
@terms = a
end
def -@; @action = :reject end
def +@; @action = :accept end
end
class << self
attr_accessor :rules
[:from, :to, :cc, :subject].each do |m|
define_method(m) do |*a|
r = Rule.new(m, *a)
(@rules ||= []) << r
r
end
end
end
end
To view the rules for mail going into the RubyTalk mailbox:
RubyTalk.rules.each do |r|
puts "[#{r.action}] if #{r.field} matches `#{r.terms}'"
end
And, the Answers
1. Where are the rules getting stored? The rules are stored in instance variables inside each class. So, not in a RubyTalk object. In the actual RubyTalk class. Right next to the methods.
2. How are the operators actually implemented? By now, you probably can see just fine. Unary operators on the Rule class. The to and from class methods create Rule classes, which then get charged positively and negatively by the operator.