Skip to content
Karel Pičman edited this page Jun 26, 2024 · 19 revisions

Workflows

Error trapping

Here is a basic workflow rule that should be the last enabled one. It is used to provide a generic message in addition to the specific errors raised by the various workflows.

# = before_save = #
raise WorkflowError, 'Errors found. Please contact the Admin for assistance as required.' unless errors.blank?

Sending custom email

This will allow you to send a custom email to anybody with a given subject and text. To find a user use User.find(#userid) function. To send an email to an external person, you can use to: [email protected] attribute. Though, user must be set too, nevertheless it isn't taken into account. You can use User.anonymous.

CustomWorkflowMailer.deliver_custom_email(user, subject: subject, text_body: text)

Watchers

# Add authors/updaters to Watchers
#
# Sets: Watcher

# = before_save = #
if subject.present?
	self.add_watcher(User.current) unless watched_by?(User.current)
end

Watchers (including assignees!)

# Add authors/assignees/updaters to Watchers
#
# Sets: Watcher

# = before_save = #
if subject.present?
	self.add_watcher(User.current) unless watched_by?(User.current)
end

# = after_save = #
# assignee - do this after save because assignee may
# be assigned by Category or by assignee plugin
if self.assigned_to.nil? || !self.assigned_to.is_a?(User) || self.assigned_to.anonymous? || !self.assigned_to.active?
  #do nothing
else
  self.add_watcher(self.assigned_to) unless self.watched_by?(self.assigned_to)
end

Creating subtask if the issue's status has changed.

# = before_save = #
@need_create = status_id_changed? && !new_record?
# = after_save = #
if @need_create
  issue = Issue.create!(
    :author => User.current,
    :project => project,
    :tracker => tracker,
    :assigned_to => author,
    :parent_issue_id => id,
    :subject => "Subtask",
    :description => "Description")
end

Prevent closing an issue if it has open descendants

# = before_save = #
if subject.present?
	if closing? && descendants.find { |d| !d.closed? }
		errors.add '', 'Cannot close an item with Open children.'
	end
end

Stripping 4 byte emojii characters which cause errors when saving

Using a bitnami stack with a MYSQL db it uses utf-8 by default. But, that cannot handle 4-byte characters, typically emojii which are used in emails, especially in Japan. So this strips those 4 byte characters and replaces them with ? in the description.

# = before_save = #
regex = /[\u{00A9}\u{00AE}\u{203C}\u{2049}\u{2122}\u{2139}\u{2194}-\u{2199}\u{21A9}-\u{21AA}\u{231A}-\u{231B}\u{2328}\u{23CF}\u{23E9}-\u{23F3}\u{23F8}-\u{23FA}\u{24C2}\u{25AA}-\u{25AB}\u{25B6}\u{25C0}\u{25FB}-\u{25FE}\u{2600}-\u{2604}\u{260E}\u{2611}\u{2614}-\u{2615}\u{2618}\u{261D}\u{2620}\u{2622}-\u{2623}\u{2626}\u{262A}\u{262E}-\u{262F}\u{2638}-\u{263A}\u{2648}-\u{2653}\u{2660}\u{2663}\u{2665}-\u{2666}\u{2668}\u{267B}\u{267F}\u{2692}-\u{2694}\u{2696}-\u{2697}\u{2699}\u{269B}-\u{269C}\u{26A0}-\u{26A1}\u{26AA}-\u{26AB}\u{26B0}-\u{26B1}\u{26BD}-\u{26BE}\u{26C4}-\u{26C5}\u{26C8}\u{26CE}-\u{26CF}\u{26D1}\u{26D3}-\u{26D4}\u{26E9}-\u{26EA}\u{26F0}-\u{26F5}\u{26F7}-\u{26FA}\u{26FD}\u{2702}\u{2705}\u{2708}-\u{270D}\u{270F}\u{2712}\u{2714}\u{2716}\u{271D}\u{2721}\u{2728}\u{2733}-\u{2734}\u{2744}\u{2747}\u{274C}\u{274E}\u{2753}-\u{2755}\u{2757}\u{2763}-\u{2764}\u{2795}-\u{2797}\u{27A1}\u{27B0}\u{27BF}\u{2934}-\u{2935}\u{2B05}-\u{2B07}\u{2B1B}-\u{2B1C}\u{2B50}\u{2B55}\u{3030}\u{303D}\u{3297}\u{3299}\u{1F004}\u{1F0CF}\u{1F170}-\u{1F171}\u{1F17E}-\u{1F17F}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F201}-\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F23A}\u{1F250}-\u{1F251}\u{1F300}-\u{1F321}\u{1F324}-\u{1F393}\u{1F396}-\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}-\u{1F3F0}\u{1F3F3}-\u{1F3F5}\u{1F3F7}-\u{1F4FD}\u{1F4FF}-\u{1F53D}\u{1F549}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F56F}-\u{1F570}\u{1F573}-\u{1F579}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F590}\u{1F595}-\u{1F596}\u{1F5A5}\u{1F5A8}\u{1F5B1}-\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5EF}\u{1F5F3}\u{1F5FA}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CB}-\u{1F6D0}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6EB}-\u{1F6EC}\u{1F6F0}\u{1F6F3}\u{1F910}-\u{1F918}\u{1F980}-\u{1F984}\u{1F9C0}]/

# description
if description_changed?
  if self.description
    self.description = [self.description,""].join
    self.description = self.description.gsub regex, '?'
  end
end

# notes_changed?
if self.notes
  self.notes = [self.notes,""].join
  self.notes = self.notes.gsub regex, '?'
end

Methods

CustomValue

# only valid in before_save scripts
def custom_value_was(cf)
	custom_value_for(cf.id).try(&:value)
end

# only valid in before_save scripts
def custom_value_changed?(cf)
	custom_field_value(cf.id) != custom_value_for(cf.id).try(&:value)
end

IssueCustomValue

# returns icf.value if visible, else nil
def visible_custom_value(icf, issue = self, user = User.current)
	issue.visible_custom_field_values(user)
	.find { |cfv| cfv.custom_field == icf }
end

# returns icf.value if editable, else nil
def editable_custom_value(icf, issue = self, user = User.current)
	issue.editable_custom_field_values(user)
	.find { |cfv| cfv.custom_field == icf }
end