C0 code coverage information
Generated on Mon May 21 22:36:02 -0400 2007 with rcov 0.8.0
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 require 'rools/errors'
2 require 'rools/default_parameter_proc'
3 require 'rools/base'
4
5 module Rools
6 class Rule < Base
7 attr_reader :name, :priority, :rule_set
8 attr_reader :parameters, :conditions, :consequences
9
10
11 # A Rule requires a Rools::RuleSet, a name, and an associated block
12 # which will be executed at initialization
13 def initialize(rule_set, name, priority, b)
14 @rule_set = rule_set
15 @name = name
16 @priority = priority
17 @conditions = []
18 @consequences = []
19 @parameters = []
20
21 begin
22 instance_eval(&b) if b
23 rescue Exception => e
24 raise RuleCheckError.new( self, e)
25 end
26 end
27
28 # Adds a condition to the Rule.
29 # For readability, it might be preferrable to use a
30 # new condition for every evaluation when possible.
31 # ==Example
32 # condition { person.name == 'Fred' }
33 # condition { person.age > 18 }
34 # As opposed to:
35 # condition { person.name == 'Fred' && person.age > 18 }
36 def condition(&b)
37 @conditions << DefaultParameterProc.new(self, b)
38 end
39
40 # Adds a consequence to the Rule
41 # ==Example
42 # consequence { user.failed_logins += 1; user.save! }
43 def consequence(&b)
44 @consequences << DefaultParameterProc.new(self, b)
45 end
46
47 # Sets the parameters of the Rule
48 # ==Example
49 # parameters Person, :name, :occupation
50 # The arguments passed are evaluated with :is_a? for each
51 # constant-name passed, and :responds_to? for each symbol.
52 # So the above example would be the same as:
53 # obj.is_a?(Person) &&
54 # obj.responds_to?(:name) &&
55 # obj.responds_to?(:occupation)
56 # You can pass any combination of symbols or constants.
57 # You might want to refrain from referencing constants to
58 # aid in "duck-typing", or you might want to use parameters such as:
59 # parameters Person, Employee, :department
60 # To verify that the asserted object is an Employee, that inherits from
61 # Person, and responds to :department
62 def parameters(*matches)
63 logger.debug( "Adding parameters: #{matches}") if logger
64 @parameters += matches
65 end
66
67 # parameters is aliased to aid in readability if you decide
68 # to pass only one parameter.
69 alias :parameter :parameters
70
71 # Checks to see if this Rule's parameters match the asserted object
72 def parameters_match?(obj)
73 @parameters.each do |p|
74 logger.debug( "#{self} match p:#{p} obj:#{obj} sym:#{Symbol}") if logger
75 if p.is_a?(Symbol)
76 #return false unless obj.respond_to?(p)
77 return true if obj.respond_to?(p)
78 else
79 logger.debug( "#{self} is_a p:#{p} obj:#{obj} #{obj.is_a?(p)}") if logger
80 #return false unless obj.is_a?(p)
81 return true if obj.is_a?(p)
82 end
83 end
84
85 # if parameters are not specified, let's assume that the rule is always relevant
86 if @parameters.size == 0
87 logger.debug "no parameters defined for rule: #{self}" if logger
88 return true
89 end
90
91 logger.debug( "no parameter match") if logger
92 return false
93 end
94
95 # Checks to see if this Rule's conditions match the asserted object
96 # Any StandardErrors are caught and wrapped in RuleCheckErrors, then raised.
97 def conditions_match?(obj)
98 begin
99 @conditions.each { |c| return false unless c.call(obj) }
100 rescue StandardError => e
101 logger.error( "rule StandardError #{e} #{e.backtrace.join("\n")}") if logger
102 raise RuleCheckError.new(self, e)
103 end
104
105 return true
106 end
107
108 # Calls Rools::RuleSet#assert in the bound working-set
109 def assert(obj)
110 @rule_set.assert(obj)
111 end
112
113 # Execute each consequence.
114 # Any StandardErrors are caught and wrapped in Rools::RuleConsequenceError,
115 # then raised to break out of the current assertion.
116 def call(obj)
117 begin
118 @consequences.each do |c|
119 c.call(obj)
120 end
121 rescue StandardError => e
122 # discontinue the Rools::RuleSet#assert if any consequence fails
123 logger.error( "rule RuleConsequenceError #{e.to_s} #{e.backtrace.join("\n")}") if logger
124 raise RuleConsequenceError.new(rule, e)
125 end
126 end
127
128 # Stops the current assertion. Does not indicate failure.
129 def stop(message = nil)
130 @rule_set.stop(message)
131 end
132
133 # Stops the current assertion and change status to :fail
134 def fail(message = nil)
135 @rule_set.fail(message)
136 end
137
138 def to_s
139 @name
140 end
141 end
142 end
Generated using the rcov code coverage analysis tool for Ruby version 0.8.0.