Skip to content
Looking for every option?See the full API reference →

Resource controllers

In order to benefit from Rails' amazing REST architecture, Avo generates a controller alongside every resource. Each generated controller inherits from Avo::ResourcesController, which inherits from Avo::BaseController — that's where every CRUD action lives.

ruby
# app/controllers/avo/courses_controller.rb
class Avo::CoursesController < Avo::ResourcesController
end

Generally speaking you don't need to touch these controllers — everything works out of the box with configuration added to the resource file. When you need more granular control over what happens in an action, override one of the hook methods below in your generated controller, similar to how devise lets you override after_sign_in_path_for.

Every hook comes in three flavors per action (create, update, destroy): a redirect path, success/failure messages, and success/failure responses. The API reference documents each one with its default behavior.

Change where the user is redirected

If you only want to send the user to the Index or Edit view after saving, you don't need the controller at all — set self.after_create_path or self.after_update_path on the resource:

ruby
# app/avo/resources/comment.rb
class Avo::Resources::Comment < Avo::BaseResource
  self.after_create_path = :index
end

For anything more custom, override after_create_path, after_update_path, or after_destroy_path in the controller:

ruby
# app/controllers/avo/courses_controller.rb
class Avo::CoursesController < Avo::ResourcesController
  def after_create_path
    "/avo/resources/users"
  end
end

The defaults do more than redirect to the record

The default paths handle cases you may want to keep: after_create_path redirects back to the parent record when the record was created through an association, and after_update_path honors the return_to and referrer params. Guard your override so those flows still work:

ruby
# app/controllers/avo/courses_controller.rb
def after_update_path
  return super if params[:return_to].present?

  "/avo/resources/courses"
end

Customize the flash messages

Override the *_success_message and *_fail_message methods to change what the user sees after each action:

ruby
# app/controllers/avo/courses_controller.rb
class Avo::CoursesController < Avo::ResourcesController
  def create_success_message
    "Course saved. Off you go! 🚀"
  end

  def destroy_fail_message
    "This course could not be removed."
  end
end

There's one per outcome: create_success_message, create_fail_message, update_success_message, update_fail_message, destroy_success_message, and destroy_fail_message.

Return a custom response

When changing the path or message isn't enough — you want a different format, extra headers, or a completely different render — override the *_action methods:

ruby
# app/controllers/avo/courses_controller.rb
class Avo::CoursesController < Avo::ResourcesController
  def create_success_action
    return super if params[:via_belongs_to_resource_class].present?

    respond_to do |format|
      format.html { redirect_to "/dashboard", flash: {success: create_success_message} }
    end
  end
end

The default responses handle Turbo flows

The default *_action implementations do more than redirect: create_success_action closes the modal and updates the field when a record is created through a belongs_to modal, destroy_success_action reloads the Turbo Frame when deleting from an association list, and the fail actions render a turbo_stream format. Fall back to super for the cases you're not customizing — see each method's default behavior in the API reference.

Change how records are saved or destroyed

Avo persists records with @record.save! and removes them with @record.destroy!. To use a different mechanism — soft deletes, a service object, extra bookkeeping — override save_record_action or destroy_record_action:

ruby
# app/controllers/avo/courses_controller.rb
class Avo::CoursesController < Avo::ResourcesController
  def destroy_record_action
    @record.archive!
  end
end

Errors raised inside these methods are caught and surfaced on the record, so the regular fail actions and messages kick in.