Shred IT!!!!

IT全般について試したこと・勉強したことを綴ったり、趣味について語るブログ

ActiveAdmin で 編集内容を Ajax を使って反映させる方法

f:id:jetglass:20150902184838j:plain

概要


ActiveAdmin で作った管理機能でフォームの更新内容を Ajax で反映させるときの方法をまとめる。
coffee script でガリガリ書かないといけないこともあるが、単純にデータの保存・上書きであれば下記の方法で大体はいけるはず。

準備


Gemfile の編集。

tylergannon/toastr-rails · GitHub
この gem を使うと javascript でいい感じのトーストを表示できる。

gem 'toastr-rails'

gem のインストールをしたら、JS, CSS で toastr を読み込むようにする。

# vim app/assets/javascripts/active_admin.js.coffee
#= require active_admin/base
#= require toastr
#= require active_admin/user
# app/assets/javascripts/active_admin.css.scss
@import "active_admin/mixins";
@import "active_admin/base";
@import "toastr.css";

仕様


下記のようなテーブルがあるとする。
3つのテーブルで has_and_belongs_to_manyの関係になっている。

users admin_users memos
id id id
name login_id user_id
password admin_user_id
memo

とある AdminUser でログインし、User に対してメモを書き残したいとする。
User 詳細画面にメモのフォームがあり、そこに書き込んでボタンを押下すると画面遷移せずに Message を保存・上書きできること。

実装


ActiveAdmin の Rails 側の実装から。
active_admin_form_for でフォームを生成し、オプションでremote: true を渡すだけで Ajax 対応フォームになる。
既存の Rails と同じように使える。

# vim app/admin/user.rb
...
show do
  row :id
  ...
  # resource は User モデルのインスタンスが入っている(example/admin/user/1 で絞り込まれたもの
  # admin_user_id で絞ったものが取得できればそれを上書きするようにセットしておく
  # 取得できない場合は create で作成してしまって、それを上書きさせる(newだとボタンを押された回数レコードがインサートされる
  memo = resource.memo_by_admin_user_id(current_admin_user.id) || resource.memos.create({admin_user_id: current_admin_user.id})
  # remote: true の指定だけでこのフォームは Ajax 通信される
  active_admin_form_for([:admin, memo], remote: true, html: { id: "admin_memo"}) do |f|
    f.inputs do
      f.input :id, as: :hidden
      f.input :user_id, as: :hidden
      f.input :admin_user_id, input_html: {value: current_admin_user.id}, as: :hidden
      f.input :memo
      f.submit
    end
  end

Ajax での通信を受け取る側、パラメータを受け取ることを許可しておく。
中身の実装はなくても ActiveAdmin が自動で CRUD を実装してくれているので下記だけで基本問題なし。

# vim app/admin/memo.rb
ActiveAdmin.register Memo do
  # メニューを非表示にする
  menu false
  permit_params :id, :user_id, :admin_user_id, :memo
end

モデルの実装は省きます。
仕様で説明した3つのテーブルで has_and_belongs_to_manyの関係になっている。

Javascript 側では Ajax の通信によって、トーストを表示させる。

# vim app/assets/javascripts/active_admin/user.js.coffee
$ ->
  $('#admin_memo')
    .on 'ajax:success', (event, data, status, xhr) ->
      toastr.success "保存しました"
    .on 'ajax:error', (xhr, status, error) ->
      toastr.error "保存できませんでした"

以上。
これだけでそこそこの画面ができてしまう。

tylergannon/toastr-rails · GitHubgithub.com

今回の記事のポイントは↑かもしれない。