class Noteikumi::Rule
A class that represents an individual rule used by the engine
Rules
are generally stored in files named something_rule.rb in a rule directory, there are several samples of these in the examples dir and in docs on the wiki at GitHub
Attributes
The concurrency safe level @api private @see {concurrency=} @return [:safe, :unsafe]
Named conditions for this rule @api private @see {condition} @return [Hash]
The file the rule was found in @api private @return [String]
The logger used by this rule @api private @return [Logger]
The rule name @api private @return [String,Symbol]
Items the rule expect on the state @api private @see {requirement} @return [Array]
The priority for this fule @return [Fixnum]
The run conditions for this rule @api private @see {run_when} @return [Proc]
How many times this rule have been run @api private @return [Fixnum]
The logic to run @api private @see {run} @return [Proc]
The state this rule is being evaluated against @api private @return [State,nil]
Public Class Methods
Creates a new rule
@param name [String,Symbol] the name of the rule @return [Rule]
# File lib/noteikumi/rule.rb, line 71 def initialize(name) @name = name @priority = 500 @concurrent = :unsafe @needs = [] @conditions = {} @state = nil @file = "unknown file" @run_count = 0 run_when { true } run { raise("No execution logic provided for rule") } end
Public Instance Methods
Assign the provided state to the rule
@param state [State] the state to store @return [void]
# File lib/noteikumi/rule.rb, line 98 def assign_state(state) @state = state end
Checks if a condition matching the name has been created on the rule
@see {#condition} @param condition [Symbol] condition name @return [Boolean]
# File lib/noteikumi/rule.rb, line 90 def has_condition?(condition) @conditions.include?(condition) end
Construct a result object for this rule
@return [Result]
# File lib/noteikumi/rule.rb, line 155 def new_result Result.new(self) end
Process a rule after first checking all the requirements are met
@param state [State] the state to use as scope @return [Result,nil] nil when the rule never ran due to state checks
# File lib/noteikumi/rule.rb, line 163 def process(state) result = nil with_state(state) do if state_meets_requirements? if satisfies_run_condition? logger.debug("Processing rule %s" % self) result = run_rule_logic else logger.debug("Skipping processing rule due to run_when block returning false on %s" % self) end else logger.debug("Skipping processing rule %s due to state check failing" % self) end end result end
Resets the run count for the rule to 0
@return [void]
# File lib/noteikumi/rule.rb, line 112 def reset_counter @run_count = 0 end
Resets the state to nil state
@return [void]
# File lib/noteikumi/rule.rb, line 105 def reset_state @state = nil end
Runs the rule logic
Rules
are run within an instance of {RuleExecutionScope}
@return [Result]
# File lib/noteikumi/rule.rb, line 133 def run_rule_logic @run_count += 1 result = new_result begin result.start_processing result.output = RuleExecutionScope.new(self).run rescue => e logger.error("Error during processing of rule: %s: %s: %s" % [self, e.class, e.to_s]) logger.debug(e.backtrace.join("\n\t")) result.exception = e ensure result.stop_processing end result end
Determines if the run_when block is satisfied
@return [Boolean]
# File lib/noteikumi/rule.rb, line 185 def satisfies_run_condition? validator = RuleConditionValidator.new(self) validator.__should_run? end
Checks every requirement against the state
@return [Boolean]
# File lib/noteikumi/rule.rb, line 193 def state_meets_requirements? @needs.each do |requirement| valid, reason = state.meets_requirement?(requirement) unless valid logger.debug("State does not meet the requirements %s: %s" % [self, reason]) return false end end true end
Assigns the state, yields to the block and resets it
@param state [State] a state to act on @return [Object] the outcome from the block
# File lib/noteikumi/rule.rb, line 120 def with_state(state) assign_state(state) yield ensure reset_state end