Defined in Rule.Def Inherits from Object Inherits interface from PeopleListTarget Abstract
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.
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.
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.
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 |
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 |
Class RuleAction defines no fields. Custom subclasses you create are likely to define fields.
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); }
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.