ActiveAdminのアクション追加例3パターン

## はじめに

ActiveAdminで開発を進めていると独自アクションを追加したいケースがあります。
本記事ではよく使うアクションの追加例を3パターン紹介します。

### アクションとは

Railsのコントローラに記述する`#index`, `#show`, `#new`, `#create`, `#edit`, `#update`, `#destroy`などのことです。

### どのような時にアクションを追加するのか

ActiveAdminでは普段使用する7種類のアクションを用意してくれますが、例えば「全ユーザを一括で更新したい」といった処理はもちろん自分でアクションを書く必要があります。
通常のRailsコントローラならroutes.rbにmemberやcollectionを書けばよいのですが、ActiveAdminではそうはいかないので本記事を書くことにしました。

参考: [Railsガイドのmemberやcollectionの解説](https://railsguides.jp/routing.html#restful%E3%81%AA%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%81%95%E3%82%89%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)

## 前提知識

- ActiveAdminを使ったことがある人
  - ActiveAdminのインストール方法などは記載しません
- Railsのコントローラやアクションの考え方がわかっている人
  - Railsの基礎的な知識は説明しません

## バージョン情報

記事公開時点の最新バージョンを使用しています。

- Ruby: `3.3.1`
- Ruby on Rails: `7.1.3`
- ActiveAdmin: `3.2.0`

## 呼び出し例

### 呼び出し例1: 全レコードに対して一括処理したい場合、または特定のレコードとは関係ない処理をしたい場合

主に一覧画面(#index)の右上にボタンを配置する例です。

```rb
action_item :call_example_1, only: :index do
  link_to '呼び出し例1', action: :call_example_1
end

collection_action :call_example_1 do
  flash[:notice] = '呼び出し例1が実行されました'
  redirect_to action: :index
end
```

`action_item`によって画面の右上にボタンを配置することができます。表示する画面は`only: :index`と書くことで一覧(#index)画面に絞りました。
[公式ドキュメント Action Items](https://activeadmin.info/8-custom-actions.html#action-items)

`collection_action`によってアクションを追加することができます。
例ではアクション名を`#call_example_1`としています。
[公式ドキュメント Collection Actions](https://activeadmin.info/8-custom-actions.html#collection-actions)

ちなみに`link_to`や`redirect_to`はActiveAdminではなくRailsのメソッドです。

![一覧画面に"呼び出し例1"というボタンを追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231426/8689ddf7-9061-d153-8481-842f035d95fb.png)

### 呼び出し例2: 1レコードに対して処理したい場合

閲覧画面(#show)の右上にボタンを配置する例です。

```rb
action_item :call_example_2, only: :show do
  link_to '呼び出し例2', { action: :call_example_2, id: params[:id] }, method: :put
end

member_action :call_example_2, method: :put do
  flash[:notice] = "呼び出し例2が実行されました (ID: #{params[:id]})"
  redirect_to action: :show, id: params[:id]
end
```

流れは呼び出し例1と似ています。
`action_item`では`only: :show`として詳細(#show)画面のみを表示対象としました。
また、処理の中で`params[:id]`とすることでIDを取得しています。

`member_action`によってアクションを追加することができます。
例ではアクション名を`#call_example_2`としています。methodはputにしてみましたが、その処理にとって適切なHTTPメソッド (`:get`や`:destroy`など) を設定するようにしてください。
[公式ドキュメント Member Actions](https://activeadmin.info/8-custom-actions.html#member-actions)

![詳細画面に"呼び出し例2"というボタンを追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231426/d755ebe9-d065-8adc-7b72-89851c78d911.png)

### (補足) collection_actionとmember_actionの違い

collection_actionとmember_actionの違いはroutes.rbに記述するcollectionとmemberの違いと同じです。
参考: [Railsガイドのmemberやcollectionの解説](https://railsguides.jp/routing.html#restful%E3%81%AA%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%81%95%E3%82%89%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)

||collection_action|member_action|
|--|--|--|
|使用ケース|一覧に対して処理したいケースや<br>直接関係ないリソースに対して処理したいケース|1件に対して処理したいケース|
|生成されるパス|`/admin/company_users/:call_example_1`|`/admin/company_users/:id/:call_example_2`|
|ルーティングヘルパー|`call_example_1_admin_company_users`|`call_example_2_admin_company_user`|

### 呼び出し例3: 選択されたレコードに対して一括処理したい場合

一覧画面で対象レコードにチェックを入れ、一括で処理する例です。

```rb
batch_action '呼び出し例3' do |ids|
  flash[:notice] = "呼び出し例3が実行されました (ID: #{ids.join(', ')})"
  redirect_to action: :index
end
```

`batch_action`には`ids` (IDの配列) が渡されます。これまでの例とは異なる流れですが、書き方は一番シンプルです。
[公式ドキュメント Batch Actions Creating your own](https://activeadmin.info/9-batch-actions.html#creating-your-own)

![一覧画面に"選択した行を呼び出し例3"というボタンを追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231426/424b594e-c198-339c-9736-fc6fbf25789a.png)

### (TIPS) デフォルトのバッチアクション削除

デフォルトでは全画面に"選択した行を削除する"というボタンが用意されています。

![選択した行を削除するボタン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231426/b662e0ea-e226-1266-472c-ea0c0c1d922f.png)

一括削除は便利かもしれませんが、誤って押下してしまう危険性があります。誤操作の危険を感じた場合は削除しておくと安全な画面設計にできるかもしれません。
[公式ドキュメント Batch Actions Removal](https://activeadmin.info/9-batch-actions.html#Removal)

```rb
batch_action :destroy, false
```

### おわりに

アクションの追加例を3パターン紹介してみました。
ActiveAdminはRailsと異なる記法が必要で苦戦することが多いですが、このあたりを抑えておけばたいていの処理は呼び出せるようになるかと思います。