rails管理画面作成gem:typusのカスタマイズ方法tips集

## 概要

webシステムを開発するときは、ユーザーの表に見えるところ以外にも
管理側で、もう一つシステムを開発する必要がありますが、ログイン回りなど実際にはどのシステムでも同じような機能を作る必要があるので、できれば管理画面もgemを使って楽々開発したいですよね!

そのための、rails周辺で有名な管理画面系gemでは次の3つが挙げられます

* [rails_admin](https://github.com/sferik/rails_admin)
* [activeadmin](https://github.com/activeadmin/activeadmin)
* [typus](https://github.com/typus/typus)

ですが、あえて今回は私が一番愛用しているtypusの使い方を解説させていただきましょう。

Typusサイト
https://github.com/typus/typus

## typusの特徴

typusの特徴は

* すべての機能が上書き可能な前提で設計されている
* そのため管理画面生成gemの中で***一番カスタマイズが効く***

というところです
とにかくやろうと思えばログイン機能だけ借りて他を全部入れ替えたりもそんなに苦労しないで出来るので、企画から様々な要求が上がってきても耐えられるんですよね。

ただ逆に、他のgemに比べて単純にインストールだけしたときの見た目は若干貧弱なところから始まるし、モデルの追加を自動で検知しないのでyamlファイルを追加するの面倒臭いので、***拡張性無視でとりあえず機能の揃っている管理画面欲しい***という需要に応えるrails_adminのお手軽さに比べると評価が低いんですよね。
(とはいえ自分も、開発中にデータを突っ込むのにはrails_adminは重宝しています。あくまで実運用には向かないと思っているだけです)

あー、あとちなみに、古い情報ではtypusはmongoDBなどのNoSQLのDBには非対応という話になっていますが、とっくにそんな事はなくなっています、そもそも今日び、mondoDBで新規開発する案件あるの？という疑問は置いておいて、そこは誤解が多いのでここで解いておきます。

私の場合は、企画から何言われてもなんとかなる事を重要視しているので、自分なりに2年程度使ってきています。
良いところ、悪いところも含めて色々分かって来たので、自分なりにtipsとして出させて頂きます。

typusは大雑把なところからだんだんと細かいカスタマイズを続けていくことが出来るようになっているので、次の順番で編集をしていくのがオススメです。

1. 生成されるYAMLファイルを編集して表示項目をカスタマイズする
2. モデルにメソッドを拡張して、表示項目に加えていく
3. コントローラーの新しい機能を追加していく
4. viewを書き換えて表示項目を変えていく

もちろん、実際には順番通りにはいかないので、モデルではなんともできないのでコントローラーを直に取って行ったり、その場に合わせた対応を取るものですが、解説はこの順番でだんだんと細かいカスタマイズが行えるようになっていきましょう。

## インストール方法

インストール方法自体は、公式サイトの情報に従ってそのままやってしまうのが良いでしょう

Gemfileにtypusの設定ファイルを記述して、以下のコマンドを実行してやるだけです

```rb
# rails4系の追随度を考えて、最新版へのリンクを貼っておく
gem "typus", git:"https://github.com/typus/typus.git"
```

```
bundle install
rails generate typus
rails generate typus:migration
bundle exec rake db:migrate
rails server
```

これで、「config/initializers/」以下に、typusの基本的な設定ファイルと
現在設定されているテーブル周りの設定を記述したyamlファイルが自動で生成されます。

あとはデフォルトの設定であれば

http://localhost:3000/admin/

に対してアクセスしてやれば、起動を確認できます。

初回のみ、ユーザー作成のフローになるので、自分のメールアドレスを入力した後に管理画面からプロフィール登録に進んでください

あとは、各テーブルの管理画面を生成するために

```
bundle exec rails generate typus
```

コマンドをもう一度実行するだけです。

## オススメ初期設定

### サイドバーの上書き

typusインストールの初期状態では、サイドバーにメッセージが表示されているので、新しいサイドバーファイルを作って上書きします

次のコマンドを実行して、所定の場所にテキストファイルを作成すればいいです

```
mkdir -p app/views/admin/dashboard
touch app/views/admin/dashboard/_sidebar.html.erb
```

### 日本語への対応

typus本体は、日本語への正式対応をしていないのですが
管理画面で、対応言語のセレクトボックスに日本語を追加する方法は、下のページにあります。まぁ、私のgithubリポジトリなのですが。

https://github.com/baban/typus_lang

最近のバージョンでは、rails本体の利用可能なロケールを見るようになったので

 * config/application.rb

に以下の設定を記述していけば、日本語が選択できるようになります

```
I18n.available_locales = I18n.available_locales.push(:ja)
```
これでうまく変わらなかった時は、AdminUser.localesメソッドのコードを辿って下さい。このあたりの定義はまだTypus側で安定していない様でバージョン毎に変わってきているので。

## YAMLファイルの編集

YAMLファイルは、一つのモデルにつき２つ生成をされます
例えば、Userモデルに対しては、次の２つが生成されますね

* config/typus/user.yml
* config/typus/user_roles.yml

それぞれが「表示する項目の管理」と、「アクセスできるユーザー権限」の管理を行います。

```yaml:config/typus/user.yml
User:
  fields:
    default: email, encrypted_password, reset_password_token, reset_password_sent_at, sign_in_count, current_sign_in_at, last_sign_in_at, current_sign_in_ip, last_sign_in_ip
    form: email, encrypted_password, reset_password_token, reset_password_sent_at, sign_in_count, current_sign_in_at, last_sign_in_at, current_sign_in_ip, last_sign_in_ip
  relationships: 
  application: Application
```

### 表示項目の編集

表示項目の編集は、公式ドキュメントの[該当部分](http://docs.typuscmf.com/configuration/resources.html)を参照するのが一番良いです

### 権限の編集

権限も[公式のドキュメント](http://docs.typuscmf.com/configuration/roles.html)を参照するのが一番充実しているのですが「_roles.yml」のついているYAMLファイルを編集してやれば良いです。

せっかく、公式で「rails generate typus」コマンドで「モデル名_roles.yaml」で自動生成してくれているので、乗っかってこれを使い続けていれば簡単です。

ですので、下のファイルを書き換えて「editor」という、管理者とちがって、ユーザーの作成ができないユーザーを作成したいときは、
「config/typus/typus_roles.yml」にユーザーの追加を行います。

```yaml:config/typus/user_roles.yml
admin:
  AdminUser: all

editor:
  AdminUser: read
```

これでeditorの権限が追加されたの、各々のモデルに対して
権限の編集を行えば良いです。

```yaml:config/typus/user_roles.yml
admin:
  # userテーブルの項目に、権限に関わらずカスタマイズ出来ていいカラムが無いので
  # updateのカラムは削っておく
  User: create, read, delete

editor:
  # ユーザー情報に関しては、基本的に検索と閲覧だけ出来れば良いので
  # 特別なユーザー以外はreadのみの指定で基本行く
  User: read
```

#### カラムの変更を無視する

typusは管理画面系gemの中ではカラムの変更に一番弱いgemで、存在しないカラムの名前がYAMLファイルの中にあると途端にその画面が500エラーを出します。

開発初期は、テーブルのカラム名も結構頻繁に変わるものなので、これは何とかしたいですが、実は、下の様にカラム名をすべて削っておくと、自動でモデルのカラム名をすべて取得して、それを代わりに使ってくれます。

YAMLファイルを生成したら、フィールド名を全て削ってしまって、テーブルの構成が安定した開発後期に、カラム名を埋め直すと便利です

```yaml:config/typus/user.yml
User:
  fields:
    # こうやってカラム名前をすべて削っておくと
    # 存在するカラム名をすべて取得してそれを代わりに表示してくれます
    default: 
  relationships: 
  application: Application
```

カラム名をすべて取得しなおすには、私の場合は「rails console」を起動してから

```rb
p User.column_names*" "
```
と打ち込むと、一気にカラム名が取得できるのでそれをYAMLにコピペしています

#### レコード項目以外の表示方法

以外と知られていませんが、実はYAMLの中で記述できるのは、カラム名だけではなかったりします

裏側ではsendメソッドを使って呼び出しを行っているだけなので、メソッドは何でも呼び出せます

そのときの翻訳の出し方はconfig/locales/translation_ja.ymlに他のカラムの翻訳と一緒に記述すればいいです。

#### belongs_toされているモデルへの参照を貼る

例えば商品説明ページのコメントをつけられる場合、コメントから商品説明ページへの参照も、typusの場合自動でリンクが貼られます。下の例では、goods_idだったカラム名をgoodsに変えるだけでその恩恵を受けられます。
※ ただし、formでこれを指定するのは参照元の行の数が少ないマスターデータなどの場合のみにした方が良いです。選択ボックスを生成しようとして、データが多すぎて本番で処理が止まったりします。

```
Goods:
  fields:
    default: id, description

Goods:
  fields:
    # goods_idではなく、belongs_toを貼っている、goodsに参照を張る
    default: id, goods, content

```


## コントローラーのカスタマイズ

### CRUD以外のアクションを追加する

typusはrerouceファイルを生成すると、index,create,show,update,deleteの５つのアクションについては自動的に面倒を見てくれます
しかし、要件が複雑になってくると他のアクションを作りたくなることが度々ありますね。

こういう時は、「_roles.yml」ファイルに、追加したいアクションの名前を書いてあげると、普通にtypusが面倒を見て追加を行ってくれます。

例えば、ユーザーの編集に関しての注意事項を書いた'caution'というアクションを追加したい場合
次の様に、まずアクションをyamlファイルに記述してやります

```rb:config/typus/user_roles.yml
admin:
  # 注意文言を記述した'caution'アクションを追加する
  User: create, read, delete, caution
```

これでアクセス権限の設定ができたので、あとはコントローラーとviewを作成してあげると
指定したユーザーにしかアクセスできない新しいアクションが追加されます

```rb:app/controllers/admin/users_controller.rb
class Admin::UsersController < Admin::ResourcesController
  # cautionアクションを追加
  def caution
  end
end
```

```erb:app/views/admin/users/caution.html.erb
<% content_for :main_grid do %>
  <h1>注意文言</h1>
  <p>以下文言…</p>
<% end %>
```

この状態で、以下の様に新しく作成されたアクションのurlを打ち込むと、注意文言が表示されるはずです

http://localhost:3000/admin/users/caution

### ログイン機能だけを間借りする

typusが自動生成してくれるのは、ActiveRecordのモデルに属するコントローラーの管理画面だけですが、実際に管理画面を開発していくと、それとは全く関係ないけど管理画面で扱いたいコンテンツが出てきます。

具体的に言うと、日々のユーザーの動向を表示する統計画面とかが対象なのですが、こういうのを作成したいときは、Admin::BaseControllerを継承したコントローラーを作成すればいいだけです

```
 bundle exec rails generate controller statistics users
```

これで生成されたコントローラーの継承元を変更してあげると出来上がりです

```rb:app/controllers/statistics_controller.rb
# 継承元をApplicationControllerからAdmin::BaseControllerに切り替える
class StatisticsController < Admin::BaseController
  def users
  end
end
```

ただ、view周りで500エラーが出る場合があります
そのときはサイドバーのviewファイルがないのが原因かもしれないので
そのファイルを以下のコマンドで生成してみてからもう一度表示状態を確認してください

```
touch app/views/admin/base/_sidebar.html.erb        
```

Admin::BaseControllerを継承すると、管理画面に入れるすべてのユーザーがこのページを見れてしまうので、さらにアクセス権限をアクションごとに付与したい場合は前の項目の「CRUD以外のアクションを追加する」を参考にAdmin::ResourcesControllerを代わりに継承してアクションの追加を行えばいいと思います

## Viewのカスタマイズ

### ヘッダーに項目を追加する

フォームやリストのページの上にちょっとした注意文言だけ追加しておきたい、でもそのほかに大きな要望は無いっていう場合、それぞれのアクションに対して

| アクション名 |    ファイル名    |
|-------------|-----------------|
|   index     | _index.html.erb |
|   new       | _new.html.erb   |
|   edit      | _edit.html.erb  |

という名前のファイルを用意すれば、文言だけをちょっと追加できるようになっています。

例えばユーザーの一覧ページのアクションに文言を表示させたい場合には
次のように「_index.html.erb」ファイルを追加してやればいいです

```erb:app/views/admin/users/_index.html.erb
<% content_for :main_grid do %>
  <div>
    <p>サンプルメッセージ</p>
  </div>
<% end %>
```

こうすると下のように、タイトルの上に文言を出すことができます。

![message_screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/10715/311bed9b-512f-d26d-b3e2-be45e56f4e38.png)


## スタイルシートのカスタマイズ

typus既存のデザインはtwitter-bootstrapで出来ています
普通は社内向けの管理画面でデザインに対するこだわりはないの
これ自体を生かしたままちょっと追加だけ行いたいというのは普通の需要ですので
それを行いたい時は、そのためのスタイルシートを所定の場所に作ってあげればいいです

置き場所は以下の場所なので、touchコマンドで作成して下さい

```css:app/assets/stylesheets/typus/custom.scss
mkdir app/assets/stylesheets/typus/
touch app/assets/stylesheets/typus/custom.scss
```

## まとめ

typus自体は、普通やりたい範囲の事はyamlの編集で出来るし
外部に公開したい時は、一から機能の上書きも出来るし、その中間も出来る。
そういう間口の広さが最大の強みです。

ただ、経験論としてtypus使ってきた感想としての忠告は
typusを使いこなそうとするよりも、維持管理しやすい設計にしたほうがいいという所を気をつけましょうということですかね。
出来るだけtypusの持っている機能を100%使いこなして管理画面を作ろうとすると
あちこちからhelper関数やインスタンス変数を借りてきたパッチワークのような画面をってしまう事になってしまい、作った自分ですら何がしたかったのか分からないコードが出来上がります。
ですので、基本方針として、一つのアクションで、コントローラーやviewのrubyコードを直接上書きする箇所が３箇所以上になったら、typusの力を借りるのではなくて、一から機能を自分で作って、必要に応じてtypusのhelperの力を借りるという方針に切り替えたほうが良いと思います。

自分も外部に公開する画面と、社内で使用する画面を、全然仕様もデザインも異なっているのに、一つの管理画面で権限だけ分けて作ろうとしてかえって訳のわからないことになって失敗したりしました。

どこの世界でもそうですが、道具に使われない感覚は大事ですね。

実際には、どういう風に運用をしているかは、続きの記事を書きました。

* [typusの我流運用法](http://qiita.com/baban/items/6a45d05dd08898198db8)