C0 code coverage information
Generated on Sat Jul 21 11:12:32 -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.inspect}") if logger
64 # @parameters += matches
65 @parameters << matches
66 end
67
68 #
69 # returns parameters of rule
70 #
71 def get_parameters
72 @parameters
73 end
74
75 # parameters is aliased to aid in readability if you decide
76 # to pass only one parameter.
77 alias :parameter :parameters
78
79 # Checks to see if this Rule's parameters match the asserted object
80 def parameters_match?(obj)
81 # if parameters are not specified, let's assume that the rule is always relevant
82 if @parameters.size == 0
83 logger.debug "no parameters defined for rule: #{self}" if logger
84 return true
85 end
86
87 @parameters.each do |params|
88 match = false
89
90 params.each do |p|
91 logger.debug( "#{self} match p:#{p} obj:#{obj}") if logger
92
93 if p.is_a?(Symbol)
94 if obj.respond_to?(p)
95 match = true
96 else
97 return false
98 end
99 elsif obj.is_a?(p)
100 match = true
101 end
102 end
103 return true if match
104 end
105
106 return false
107 end
108
109 # Checks to see if this Rule's conditions match the asserted object
110 # Any StandardErrors are caught and wrapped in RuleCheckErrors, then raised.
111 def conditions_match?(obj)
112 begin
113 @conditions.each { |c| return false unless c.call(obj) }
114 rescue StandardError => e
115 logger.error( "conditions_match? StandardError #{e} #{e.backtrace.join("\n")}") if logger
116 raise RuleCheckError.new(self, e)
117 end
118
119 return true
120 end
121
122 # Calls Rools::RuleSet#assert in the bound working-set
123 def assert(obj)
124 @rule_set.rule_assert(obj)
125 end
126
127 # Execute each consequence.
128 # Any StandardErrors are caught and wrapped in Rools::RuleConsequenceError,
129 # then raised to break out of the current assertion.
130 def call(obj)
131 begin
132 @consequences.each do |c|
133 c.call(obj)
134 end
135 rescue Exception => e
136 # discontinue the Rools::RuleSet#assert if any consequence fails
137 logger.error( "rule RuleConsequenceError #{e.to_s} #{e.backtrace.join("\n")}") if logger
138 raise RuleConsequenceError.new(self, e)
139 end
140 end
141
142 # Stops the current assertion. Does not indicate failure.
143 def stop(message = nil)
144 @rule_set.stop(message)
145 end
146
147 # Stops the current assertion and change status to :fail
148 def fail(message = nil)
149 @rule_set.fail(message)
150 end
151
152 def to_s
153 @name
154 end
155 end
156 end
Generated using the rcov code coverage analysis tool for Ruby version 0.8.0.