Skip to content
How-to guides and worked examplesSee the guides →

Collaboration API ​

Per-option reference for the collaboration add-on. For task-oriented documentation, installation, and worked examples, see the Collaboration guide.

Collaboration is configured per resource through the self.collaboration hash, plus the collaboration_timeline DSL method and a set of policy methods:

ruby
# app/avo/resources/project.rb
class Avo::Resources::Project < Avo::BaseResource
  self.collaboration = {
    # options listed below
  }

  def fields
    # ...
    collaboration_timeline
  end
end

Resource configuration ​

Keys of the self.collaboration hash.

author

Configures how the timeline displays the author of comments, reactions, and automatic entries. The author itself is resolved from Avo::Current.user, unless a watcher sets its own author; this hash only controls display.

ruby
self.collaboration = {
  author: {
    name_property: :name
  }
}
  • Type: Hash
  • Default: nil
  • Keys:
KeyTypeDescription
name_propertySymbol or StringThe attribute on the author object holding their display name

watchers

An array of watchers. Each watcher records an automatic timeline entry whenever the given attribute changes on the record.

ruby
self.collaboration = {
  watchers: [
    {
      property: :name,
      message: -> { "#{property} changed: #{old_value} → #{new_value}" }
    },
    { property: :status, i18n_message_key: "avo.collaboration.custom_property_changed_html" },
    { property: :stage }
  ]
}
  • Type: Array of Hashes
  • Default: nil
  • Keys:
KeyTypeDescription
propertySymbol or String(required) The attribute to watch for changes.
messageProcBuilds a custom message for the entry. Executed with resource, record, property, old_value, and new_value in scope.
i18n_message_keyStringAn I18n key used to translate the message instead of a message proc.
authorProcReturns the entry's author. Executed with the same scope as message. Defaults to Avo::Current.user.
hide_valuesBooleanWhen true, the entry is saved without old_value and new_value, and the timeline shows the message instead of the change. Defaults to false.

When a watcher provides neither message nor i18n_message_key, Avo falls back to the avo.collaboration.property_changed translation.

Changes made outside Avo

Avo::Current.user is only set inside Avo's controllers, so a change made from your app's own pages, a background job, or the console has no author by default. Use author to name one, for example the user your app tracks in Current.user.

Watching secrets

Use hide_values: true on columns that hold secrets, like API keys or tokens, so the value is never stored or shown in the timeline. The message and author procs still receive the real values, and the message is stored as-is, so don't interpolate the secret into it.

ruby
self.collaboration = {
  watchers: [
    { property: :key, message: -> { "Rotated the license key" }, author: -> { Current.user }, hide_values: true }
  ]
}

Safe HTML translations

When the translation key ends in _html, Rails treats the value as safe HTML, so message translations may contain markup. See Rails' safe HTML translations.

reactions

Customizes the emoji available when reacting to timeline entries.

ruby
self.collaboration = {
  reactions: {
    options: %w[👍 👎 ❤️ 🚀 👀]
  }
}
  • Type: Hash with key options (Array of Strings)
  • Default: 👍 👎 😀 🎉 😕 ❤️ 🚀 👀 💡 🔥
  • Behavior: Reactions are always enabled. When reactions is omitted, the default set above is used; supply options to replace it with your own list.

Timeline ​

collaboration_timeline

DSL method called inside a resource's fields block. Renders the collaboration timeline — comments, reactions, and automatic property-change entries — at the position where it's called.

ruby
def fields
  field :id, as: :id
  field :name

  collaboration_timeline
end
  • Type: DSL method (no arguments)

Authorization ​

Policy methods, defined on your resource's Pundit-style policy, that gate access to the timeline. Each returns a boolean. These extend Avo's authorization system.

collaboration_view_timeline?

Whether the user can view the timeline on a record, read its entries and react to them.

ruby
# app/policies/project_policy.rb
def collaboration_view_timeline?
  show?
end
  • Type: Policy method returning Boolean

collaboration_create_entry?

Whether the user can create new entries (comments and messages).

ruby
# app/policies/project_policy.rb
def collaboration_create_entry?
  current_user.team_member? && show?
end
  • Type: Policy method returning Boolean

collaboration_destroy_entry?

Whether the user can destroy an entry. The record passed to the policy is either an action entry (generated automatically when a watched attribute changes) or a comment entry (Avo::Collaboration::Comment, posted by a user).

ruby
# app/policies/project_policy.rb
def collaboration_destroy_entry?
  return true if current_user.admin?

  record.is_a?(Avo::Collaboration::Comment) && record.author == current_user
end
  • Type: Policy method returning Boolean