forest_admin_datasource_zendesk gem ships two plugins that surface Zendesk operations as actions on any host collection of your back-end, typically a collection that already carries the Zendesk requester’s identity (an email column) or the Zendesk ticket id (a column like last_zendesk_ticket_id).
Both plugins require the Zendesk datasource to be registered on your back-end: they need the Datasource instance to reach the Zendesk API client.
Usage
Nothing is registered automatically. Opt each plugin in per collection through the standard customizer DSL:Datasource instance you registered earlier as the required datasource: option. You can attach the same plugin to multiple collections (e.g. Customer and Order) with different option sets.
CreateTicketWithNotification
A Single-scope action that opens a Zendesk ticket from the selected host record. The host record does not need to be related to Zendesk, the requester is identified by an email entered (or pre-filled) in the form, and Zendesk creates the user record on the fly if it does not already exist (the action derives the user’s name from the email’s local-part, e.g. john.doe@acme.com → john.doe, to satisfy Zendesk’s non-empty-name validation).
| Option | Description |
|---|---|
datasource | Required. The ForestAdminDatasourceZendesk::Datasource instance. |
action_name | Overrides the action label. Defaults to 'Create ticket and notify'. |
default_subject | String used to pre-fill the “Subject” field. Supports {{record.<field>}} tokens resolved against the selected record when the form opens. |
default_message | String used to pre-fill the “Message” field. Same token syntax; rendered through a RichText widget and shipped as html_body. Token values are HTML-escaped. Ignored when email_templates is set (the wizard takes over). |
email_templates | Array of { title:, content: } hashes. When non-empty, the form becomes a two-page wizard (see below). |
requester_email_default | Default for the “Requester email” form field. Accepts a String (supports the same {{record.<field>}} tokens as Subject/Message) or a record -> email_string Proc evaluated against the selected record when the form opens. |
sender_email | Maps to Zendesk’s recipient on the created ticket, the support address replies are sent FROM. When unset, Zendesk uses the account’s default support address. |
priority_override | When set, the “Priority” dropdown is removed from the form and this value is forced in the payload (e.g. 'high'). |
type_override | Same idea for the “Type” dropdown (e.g. 'incident'). |
show_internal_note | When truthy, adds the “Send as internal note” checkbox to the form. Hidden by default, tickets are public unless this is opt-in. |
ticket_id_field | Writable column on the host collection that receives the freshly-created ticket id. Best-effort: a writeback failure is logged and surfaced in the success message without rolling back the ticket. |
| Field | Type | Notes |
|---|---|---|
| Requester email | String | Required. Pre-filled by requester_email_default. |
| Subject | String | Required. Default supports {{record.<field>}} tokens. |
| Message | RichText | Required. Sent as the ticket’s first comment (html_body). Token values inside the default are HTML-escaped. |
| Priority | Enum | Defaults to normal. Values: low, normal, high, urgent. Removed from the form when priority_override is set. |
| Type | Enum | Optional. Values: problem, incident, question, task. Removed from the form when type_override is set. |
| Send as internal note | Boolean | Hidden by default. Surfaces only when show_internal_note: true is set. When checked, the first comment is private and no notification email is sent to the requester. |
sender_email is set, that address is used as the support recipient (the From address of the outbound email).
Email-templates wizard
Whenemail_templates is set, the form becomes a two-page wizard:
- Page 1, Template. A
Templatedropdown lists each template’stitleplus a sentinel"No template"entry. Selecting an entry pre-fills the Message on page 2. - Page 2, Body. The same fields as above, with the Message pre-filled from the selected template’s
content. Picking a different template (then clicking back) re-fills the Message; typing into Message in between is preserved across re-fetches of the same template selection.
content supports the same {{record.<field>}} token syntax as default_message, and the interpolated values are HTML-escaped before being injected into the RichText editor. Picking "No template" yields an empty Message, default_message is intentionally ignored in wizard mode so the strict opt-in stays predictable.
CloseTicket
Registers actions that transition a Zendesk ticket to solved or closed. The plugin reads the ticket id from a configurable column on the host record(s), so you can close a Zendesk ticket directly from a Customer row that stores last_zendesk_ticket_id, without having to navigate to the ZendeskTicket collection.
| Option | Description |
|---|---|
datasource | Required. The ForestAdminDatasourceZendesk::Datasource instance. |
ticket_id_field | Required. Name of the column on the host record that holds the Zendesk ticket id. |
statuses | Subset of %w[solved closed]. Defaults to both. Accepts symbols (%i[solved]) or strings interchangeably. |
scopes | Subset of %i[single bulk]. Defaults to both. Accepts symbols or strings interchangeably. |
statuses and scopes are orthogonal, the plugin registers one action per (status, scope) pair, so the full default registers four actions on the host collection:
| Status | Single-scope label | Bulk-scope label |
|---|---|---|
solved | ”Mark Zendesk ticket as solved" | "Mark selected Zendesk tickets as solved” |
closed | ”Mark Zendesk ticket as closed" | "Mark selected Zendesk tickets as closed” |
statuses: %w[closed], scopes: %i[bulk] registers a single bulk-close action.
Status semantics
solvedis the standard “resolved” workflow; the requester can still reopen the ticket during Zendesk’s reopen window.closedis terminal. Zendesk rejects further updates to a closed ticket and sometimes rejects the directopen → closedtransition.
- Targeting
closedon an already-closed ticket → success (counted as “was already closed”). - Targeting
solvedon an already-closed ticket → failure (“ticket is already closed (cannot reopen to mark as solved)”).