previous chapter contents page top page next chapter

RuleAction

February 14, 1995

Defined in Rule.Def 
Inherits from Object
Inherits interface from PeopleListTarget
Abstract


Class Description

Class RuleAction provides the framework for defining the actions that rules trigger. Every rule must have a rule action, if it is to do anything when triggered.

Remember that if the documentation and the software (especially the definition files) disagree, always trust the software.

Using a RuleAction Object

You'll never use an object of class RuleAction, since class RuleAction is abstract. Instead, you'll use objects of one of RuleAction's subclasses, like class LocalRuleAction or class BuiltinRuleAction. You might create custom subclasses of class RuleAction if one of the provided classes doesn't meet your needs. The section on Programming Information gives a detailed example of how to subclass RuleAction.

Programming Information

Instantiate: never
Subclass: often
Call its methods: rarely

Class RuleAction is abstract. None of its methods do anything. You must override at least PerformRule and ComputeRuleText if you subclass class RuleAction. This section gives a detailed example showing you one way you might subclass RuleAction.

Suppose you want to write a rule action that frobs a mythical gizmo of the user's choice when a rule is triggered. ("Frob" is an extremely technical term that means something like "tickle.") Your class definition might look like this:

Define Class GizmoRuleAction;
    inherits from RuleAction;
    field gizmoObject: Object, noCopy, getter;
        // the gizmo to frob when the rule is triggered
    attribute GizmoObject: Object;
    overrides PerformRule;
        // overridden to frob the gizmo
    overrides ComputeRuleText;
        // overridden to map gizmo name text
End Class;

The descriptions of the PerformRule and ComputeRuleText methods give details on how class GizmoRuleAction would override.

If your new rule action type is used by editable rules, you should make sure that the rule is dirtied correctly when a user edits it. Dirty a rule when a piece of it changes. The class GizmoRuleAction example should dirty a rule when its GizmoObject attribute is set. It does so by defining its action setter method like this:

Method void
GizmoRuleAction_SetGizmoObject(ObjectID self, ObjectID newGizmo)
    {
    ObjectID rule;
    /* if the new gizmo is the same as the old gizmo,
       don't do anything *.
    if (newGizmo == Field(self, gizmoObject))
        return;
    /* set the field to the new gizmo */
    SetField(self, gizmoObject, newGizmo);
    /* we'll assume the user has just edited the 
       rule, and update the display in the rule view */
    rule = DirectID(iCurrentRule);
    UpdateText(rule); /* update the rule's text */
    DirtyRule(iCurrentRuleView); /* tell the rule view we changed */
    }

Your subclass should do something similar if it has data that the user can edit.

Methods defined by class RuleAction

Class RuleAction defines the following methods:

Method Description
PerformRule Carry out the action specified by the rule; does nothing by default
ComputeRuleText Create the text description of the rule; does no mapping by default
PrepareEditControl Set up a control to edit the rule's entity
SetEntity Set the entity associated with the rule action (for cloud rules)
EditStepsForNewEntity Use the default steps to create a new entity

Methods you might override

Whenever you create a subclass of class RuleAction, you should override the following methods:

Method When to override
PerformRule To implement a new rule action type
ComputeRuleText To map your rule's template text

Fields defined by class RuleAction

Class RuleAction defines no fields. Custom subclasses you create are likely to define fields.

Method Descriptions

PerformRule

operation PerformRule(contextObject: Object; rule: Object)

Call: rarely
Override: always

The system calls PerformRule to carry out the action of a rule that's been triggered and qualified.

You might want to subclass RuleAction and override PerformRule if your rule action doesn't fit into one of the action types predefined by class LocalRuleAction.

Our example class GizmoRuleAction defines PerformRule this way:

Method void
GizmoRuleAction_PerformRule(ObjectID self, long triggerData, ObjectID rule)
    {
    ObjectID gizmo = Field(self, gizmoObject);
    /* Frob the gizmo with the trigger data if we 
       have a gizmo to frob */
    if (gizmo) Frob(gizmo, triggerData); 
    }

ComputeRuleText

operation ComputeRuleText(rule: Rule; mapping: Object);

Call: rarely
Override: always

The system calls ComputeRuleText while updating a rule's text for display in a rule view. It calls this method from Rule_UpdateText, immediately after calling ComputeRuleText on the rule's qualifier. RuleAction_ ComputeRuleText does nothing. Override ComputeRuleText if you intend to use your custom rule action with editable rules.

ComputeRuleText should replace lines in the text object passed in the mapping parameter with the appropriate text.

Suppose you have an editable rule with an action object of class GizmoRuleAction, the example described earlier in this chapter. Your rule might have template text like this:

Instance Text 150;
       text: 'When a message from /person/ arrives, '\
             'frob the /gizmo name/ gizmo.';
End Instance;

Class GizmoRuleAction needs these text mapping objects to map its text:

Instance TextMapping 200;
    keyText: (Text 201);
  valueText: (Text 202);
End Instance;

Instance Text 201;
       text: 'gizmo name\nperson';
End Instance;

Instance Text 202;
End Instance;

The ComputeRuleText method for class GizmoRuleAction would replace the first line of the text mapping, like this:

Method void
GizmoRuleAction_ComputeRuleText(ObjectID self, ObjectID rule, ObjectID 
mapping)
   {
   Str255 str;
   ObjectID gizmoObject = Field(self, gizmoObject);
   if (gizmoObject)
      {
      GetName(gizmoObject, str);
      SetLine(mapping, 1, str);
      }
   }

If you're using an object of class LocalRuleQualifier for your qualifier object, you will need to stick to the standard text mapping object, iRuleTextMapping. If you want to use iRuleTextMapping, just steal one of the existing mappings and use it for your own purposes. For example, you could use /sound/ instead of /gizmo name/.

For another example of how ComputeRuleText might be implemented, see the chapter on class LocalRuleAction.