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

Actions API

Per-option reference for actions. For task-oriented documentation and worked examples, see the Actions guide.

Options live in two places: registration options are passed when declaring the action in a resource's actions method, and class attributes are set on the action class itself.

ruby
# app/avo/resources/user.rb — registration options
class Avo::Resources::User < Avo::BaseResource
  def actions
    action Avo::Actions::ToggleInactive, icon: "heroicons/outline/globe"
  end
end

# app/avo/actions/toggle_inactive.rb — class attributes
class Avo::Actions::ToggleInactive < Avo::BaseAction
  self.name = "Toggle Inactive"
  self.standalone = false
end

Options that accept a block are executed using Avo::ExecutionContext, with access to resource, record, view, arguments, and query (plus the extras listed on each option).

Registration

Declared inside the resource's actions method.

action

Registers an action class on the resource. The action appears in the Actions dropdown in the order of declaration.

ruby
def actions
  action Avo::Actions::ToggleInactive
end
  • Type: action class, plus optional arguments and icon keyword arguments

arguments

Custom data passed to the action. Accessible as arguments throughout the action class, including the handle and fields methods.

ruby
def actions
  action Avo::Actions::ToggleInactive,
    arguments: {
      special_message: true
    }

  # Or as a proc to make it dynamic
  action Avo::Actions::ToggleInactive,
    arguments: -> do
      {special_message: resource.view.index? && current_user.is_admin?}
    end
end
  • Type: Hash or Proc returning a Hash
  • Default: {}

INFO

Arguments are encrypted and Base64-encoded when embedded in action URLs, so sensitive values don't leak into the query string.

icon

The icon displayed next to the action in the dropdown. Accepts Heroicons and Tabler icon paths.

ruby
def actions
  action Avo::Actions::ToggleInactive, icon: "heroicons/outline/globe"
end
  • Type: String
  • Default: "tabler/outline/player-play"

divider

Renders a visual separator in the actions dropdown, grouping related actions. Pass label to title the group.

ruby
def actions
  action Avo::Actions::ActivateUser
  action Avo::Actions::DeactivateUser

  divider label: "Communication"

  action Avo::Actions::SendWelcomeEmail
end
  • Options: label (String, optional)

Class attributes controlling the action's display and confirmation modal. Each accepts a static value or a block.

name

The action's display name, shown in the dropdown and as the modal title.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.name = "Release fish"

  # Or as a block
  self.name = -> {
    record.present? ? "Release #{record.name}?" : "Release fish"
  }
end
  • Type: String or Proc
  • Default: nil — the class name is humanized (ToggleInactive → "Toggle inactive")

description

A short description displayed below the action's name in the modal header, helping users understand what the action does before confirming.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.description = "Release the fish back into the ocean"

  # Or as a block
  self.description = -> {
    record.present? ? "Release #{record.name} back into the ocean" : "Release fish back into the ocean"
  }
end
  • Type: String or Proc
  • Default: nil

message

The confirmation message shown in the modal body.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.message = "Are you sure you want to release the fish?"

  # Or as a block
  self.message = -> {
    if record.present?
      "Are you sure you want to release #{record.name}?"
    else
      "Are you sure you want to release the fish?"
    end
  }
end
  • Type: String or Proc
  • Default: "Are you sure you want to run this action?"
  • i18n key: avo.are_you_sure_you_want_to_run_this_option ("Are you sure you want to run this action?")

confirm_button_label

The label of the modal's confirmation button.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.confirm_button_label = "Release fish"

  # Or as a block
  self.confirm_button_label = -> {
    record.present? ? "Release #{record.name}" : "Release fish"
  }
end
  • Type: String or Proc
  • Default: "Run"
  • i18n key: avo.run ("Run")

cancel_button_label

The label of the modal's cancel button.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.cancel_button_label = "Cancel release"

  # Or as a block
  self.cancel_button_label = -> {
    record.present? ? "Cancel release on #{record.name}" : "Cancel release"
  }
end
  • Type: String or Proc
  • Default: "Cancel"
  • i18n key: avo.cancel ("Cancel")

confirmation

Whether the confirmation modal is displayed before execution. When false, the action executes immediately upon triggering — useful for actions that are safe to run without confirmation or that are part of a multi-step workflow where confirmation is handled elsewhere.

ruby
class Avo::Actions::ReleaseFish < Avo::BaseAction
  self.confirmation = false
end
  • Type: Boolean or Proc
  • Default: true

close_modal_on_backdrop_click

Whether clicking the backdrop closes the modal. Set to false to force the user to use the buttons — for example when the modal holds a form you don't want dismissed accidentally.

ruby
class Avo::Actions::ToggleInactive < Avo::BaseAction
  self.close_modal_on_backdrop_click = false
end
  • Type: Boolean
  • Default: true

Behavior

standalone

Whether the action can run without selected records. Standalone actions stay enabled in the Actions dropdown when nothing is selected, and handle receives an empty query.

ruby
class Avo::Actions::GlobalReport < Avo::BaseAction
  self.standalone = true
end
  • Type: Boolean
  • Default: false

visible

Controls the views on which the action is displayed.

ruby
class Avo::Actions::GlobalReport < Avo::BaseAction
  self.visible = -> { view.index? }
end
  • Type: Boolean or Proc
  • Default: visible on every view except New

Block extras beyond the Avo::ExecutionContext defaults:

  • view — the current view type (index, show, edit)
  • resource — the current resource instance
  • parent_resource — the parent resource, if any (access the parent record via parent_resource.record)
  • params

authorize

Restricts access to the action based on custom logic. Unauthorized actions are hidden; if a bad actor attempts to run one anyway, the controller re-evaluates the authorization and blocks the request.

ruby
class Avo::Actions::GlobalReport < Avo::BaseAction
  self.authorize = -> { current_user.is_admin? }
end
  • Type: Boolean or Proc
  • Default: true

Block extras beyond the Avo::ExecutionContext defaults: action, resource, view.

turbo

Controls the Turbo behavior of the action's form submission. Set to false when the action shouldn't be performed with Turbo — for example when it triggers a full file download response.

ruby
class Avo::Actions::ToggleInactive < Avo::BaseAction
  self.turbo = false
end
  • Type: Boolean
  • Default: unset (Turbo enabled)

The handle method

The method every action implements. Receives keyword arguments:

ArgumentDescription
queryThe selected record(s). A single record is wrapped in an array for consistency.
recordsAlias of query.
fieldsThe values submitted through the action's form fields.
current_userThe currently authenticated user.
resourceThe Avo resource instance that triggered the action.
requestThe current ActionDispatch::Request object.
ruby
def handle(query:, fields:, current_user:, resource:, request:, **args)
  # your business logic
end

Feedback methods

Called inside handle to queue notifications shown after the action completes. Call several to stack multiple notifications. With no explicit feedback, Avo shows a translated "Action ran successfully" info notification.

Each method accepts an optional timeout keyword — milliseconds the notification stays visible, or :forever to keep it open until dismissed.

ruby
succeed "Task completed successfully", timeout: 5000
warn "Important warning - requires attention", timeout: :forever
  • Default timeout: config.alert_dismiss_time (5000 ms)

INFO

Notification bodies are truncated to 320 characters.

succeed

Displays a green success alert to indicate successful completion.

inform

Displays a blue info alert for general information.

warn

Displays an orange warning alert for cautionary messages.

error

Displays a red error alert to indicate failure or errors.

silent

Suppresses the default notification. Useful for redirect scenarios where a flash message would be noise.

ruby
def handle(**args)
  redirect_to "/admin/some-tool"
  silent
end

Response methods

Called inside handle to control how the UI responds after execution. The last response method called wins; feedback notifications are flashed alongside whichever response runs.

reload

Triggers a full-page reload. This is the default behavior when no other response is specified.

ruby
def handle(query:, **args)
  query.each { |project| project.update! active: false }

  succeed "Done!"
  reload # optional — reload is the default
end

redirect_to

Redirects to another path of your app. Accepts a path or a block returning one, plus allow_other_host, status, and any other redirect arguments.

ruby
def handle(query:, **args)
  succeed "Done!"
  redirect_to avo.resources_users_path
  # or with options
  # redirect_to path, allow_other_host: true, status: 303
end

download

Starts a file download with the given content and filename.

ruby
def handle(query:, **args)
  report_data = query.map(&:generate_report_data).join("\n")

  succeed "Done!"
  download report_data, "projects.csv"
end

keep_modal_open

Keeps the modal open with the user's input intact — typically to show an error and let them retry.

ruby
def handle(fields:, **args)
  User.create fields
  succeed "All good ✌️"
rescue => error
  error "Something happened: #{error.message}"
  keep_modal_open
end

close_modal

Closes the modal via Turbo Streams and flashes the queued feedback notifications, keeping the page as it is — useful when the page holds a filled-in form you don't want reloaded.

ruby
def handle(**args)
  succeed "Modal closed!!"
  close_modal
end

do_nothing

Alias for close_modal.

Redirects to another action's modal, optionally passing arguments along — the building block for multi-step flows. See Build a multi-step flow for a worked example.

ruby
def handle(query:, fields:, **args)
  navigate_to_action Avo::Actions::City::Update,
    arguments: {
      cities: query.map(&:id)
    }
end

append_to_response

Appends additional turbo stream responses to the default turbo_stream response. Accepts a Proc executed in the context of the action's controller response; it should return a single turbo_stream response or an array of them.

ruby
def handle(**args)
  succeed "Done!"
  close_modal

  append_to_response -> {
    [
      turbo_stream.set_title("Cool title"),
      turbo_stream.set_title("Cool title 2")
    ]
  }
end

reload_records

Refreshes only the affected table rows or grid cards via Turbo Streams instead of reloading the whole page. Accepts an array of records or a single record; reload_record is an alias.

ruby
def handle(query:, fields:, **args)
  query.each do |record|
    record.update! active: !record.active
  end

  reload_records(query)
end

WARNING

This response only works on Index pages, not on associations.

Class methods

Returns the [path, data] pair needed to build a link that opens the action's modal. Called on the action class with a resource instance (with or without a hydrated record) and optional arguments.

ruby
path, data = Avo::Actions::City::Update.link_arguments(
  resource: Avo::Resources::City.new(record: city),
  arguments: {
    cities: [city.id]
  }
)

link_to "Update city", path, data: data
  • Returns: [path, data] — pass both to link_to
  • arguments are encrypted and Base64-encoded into the URL

See Trigger an action from a link for worked examples.