Rails管理画面gem の新星！administrate を使おう - その2 基本カスタマイズ

この記事は Rails管理画面gem の新星！administrate を使おう のその２です。

関連記事はこちら

- [Rails管理画面gem の新星！administrate を使おう - その0 紹介 - Qiita](http://qiita.com/mm36/items/253b32f152aa94e93fda)
- [Rails管理画面gem の新星！administrate を使おう - その1 導入 - Qiita](http://qiita.com/mm36/items/c36c7a95e4e836dbffef)
- この記事
- [Rails管理画面gem の新星！administrate を使おう - その3 有名Gemと連携 - Qiita](http://qiita.com/mm36/items/bd70adb4a80071f0c015)
- [TBD] Rails管理画面gem の新星！administrate を使おう - その4 もっとカスタマイズ！

- - -

さらっと触っただけで、早速以下の項目がカスタマイズ対象でした。。

- ~~セレクトボックスがない~~ → [v0.1.5で追加されたようです！](https://github.com/thoughtbot/administrate/blob/master/CHANGELOG.md#015-april-1-2016)
- パスワードフィールドがない（comming soon)
- 日本語のローカライズPRがまだリリースに取り込まれてない(comming soon)

カスタマイズしやすい！と謳われているAdministrateの実力やいかに・・

ここからは[公式ドキュメント](http://administrate-prototype.herokuapp.com/)に記載されていない細かい情報の拾い方も合わせて紹介します。

Tipsが世の中に溢れていない、まだ新しいgemとの付き合い方を紹介！（Rails初心者必見かも！？）



## 基本的なカスタマイズ方法について

まず、基本的なカスタマイズ方法を [公式ドキュメント カスタムフィールド](http://administrate-prototype.herokuapp.com/adding_custom_field_types) より。
カスタマイズ例では Gravatars を扱えるカスタムフィールドを作っています。

公式のドキュメント、かなりわかりやすいので日本語訳はやるまでもない。。
ということで、実際に上記のやり方を踏まえた上で、というスタンスで以下進んでいきます。



### セレクトボックス

~~よくあるセレクトボックスの入力ですが、残念ながら現在の Administrate には備え付けられていません。~~
↓
[v0.1.5で追加されたようです！](https://github.com/thoughtbot/administrate/blob/master/CHANGELOG.md#015-april-1-2016)


・・・ので、以下のセレクトボックスカスタムフィールド追加は v0.1.5 以降を導入する場合は不要になりました。
以下はカスタムフィールドを追加する際の手順一例として残しておきます・・（たくさん書いたから消したくないともいう・・）

- - -
（v.0.1.5以降なら不要）
こんなやつ

![image](https://qiita-image-store.s3.amazonaws.com/0/5691/fdf8a790-0158-7ab3-884e-b364fe4674de.png)

（ラジオボタンとかチェックボックスでも良いけど・・それもない・・）
ここではセレクトボックスをカスタムフィールドで追加する方法を紹介します。

### ・・・とその前に・・下調べ重要！

「いやいや、セレクトボックスくらい、標準であるでしょ！やり方わかってないだけでしょ！！」と思うじゃないですか。（思いました・・）
ほんとーに存在しないのか、まずはチェックします。

#### <i class="fa fa-check-square"></i> ここで『知らないgemの歩き方』をご紹介！

ここに来るまでにググってるうちに気づいたのですが、このgem新しいので公式のGithubリポジトリにしか情報が存在しない・・
というわけで、Google検索よりGithubの中だけで検索をかけることにします。

- [公式のGithubリポジトリへ](https://github.com/thoughtbot/administrate/)
- 左上の Search から This repository に絞られている状態で、それらしい単語を入れてみる

![image](https://qiita-image-store.s3.amazonaws.com/0/5691/622c0c37-d23c-12e5-1891-7ffe4b883ade.png)

- 今回は "select box" って入れてみた

![image](https://qiita-image-store.s3.amazonaws.com/0/5691/57d8e918-39bc-6c76-ed33-e35023ea2440.png)

- 左側のサイドバーに Code 4, Issues 11 と出てきました。
- Issuesの方が自分のお悩みに近いことを誰か質問してる可能性が高いので詳しく見てみます

Issues の一個目を見てみると。。なんとラッキー！ビンゴな回答を発見しました♪

↓見つけたお宝Issue

[Feature request/ Way to do dropdown/select boxes for enums...etc? · Issue #420 · thoughtbot/administrate](https://github.com/thoughtbot/administrate/issues/420)

完成のスクショまで載せてくれて、なんと素晴らしい人。
これを丸パクリで解決だぜーといいうことでやってみました。

### やってみる

#### generator 実行

ターミナルで以下を実行。

```
> rails generate administrate:field select
```

ファイルが生成されます。

- app/fields/select_field.rb
- app/views/fields/select_field/_show.html.erb
- app/views/fields/select_field/_index.html.erb
- app/views/fields/select_field/_form.html.erb

#### ・・・とその前に・・状態を保存 - git を正しく使う

とりあえずごちゃごちゃ色々やる前に、ここで一旦 git commit しとくのがオススメ。
generator が作ったままのコードを1 commitに分けておくと、後で自分が追加した分がダメだったのかわかりやすいし、レビューしてくれる人のためにも良い。

```
> git add .
> git commit
```

その際コミットメッセージには、generator生成だぞーというのがわかりやすいように書くと吉。
こんな感じが良いかと。。

```
[administrate] rails generate administrate:field select

add custom field for select

see: https://github.com/thoughtbot/administrate/issues/420
```

1行目で「generator生成だぞー」っぽさを出す。
せっかく見つけたお宝 Issue のリンクも貼っておきましょう。

### 必要な変更を加える

#### 使えるヘルパーメソッドを定義

生成されたファイルのうち、どこに変更を加えるか見極める。

viewの中から呼び出す便利メソッドはこっちに定義するみたい。
以下を追記する。

```app/fields/select_field.rb
require "administrate/fields/base"

class SelectField < Administrate::Field::Base
  def to_s
    data
  end

  # 追加！
  def choices
    choices = options.fetch(:choices)
    if choices.is_a? Hash
      choices
    else
      choices.zip(choices)
    end
  end

  # 追加！
  def with_blank
    options[:with_blank]
  end

  # 追加！
  def selected_choice
    data
  end
end
```

お宝issueで見つけたコードに、若干オリジナル感を加えてみた。
（更に@patrush さんから編集リクエストを頂きました）

オプションで ```with_blank: true``` が来た場合、セレクトボックスの1つ目を値なしを選択できるようにしてみた。

``` options ``` は Dashboard から ```with_options``` でデータを渡せる。（後述）

#### パーシャルビューで見た目調整

以下は名前からして明らかに view partial なのでわかりやすい。

- app/views/fields/select_field/_show.html.erb
- app/views/fields/select_field/_index.html.erb
- app/views/fields/select_field/_form.html.erb

今回は form の入力形式のみなので、変更は1ファイルだけ。

```app/views/fields/select_field/_form.html.erb
<div class="field-unit__label">
  <%= f.label field.attribute %>
</div>

<div class="field-unit__field">
  <%= f.select(field.attribute, field.choices, include_blank: field.with_blank) %>
</div>
```

さっき ```app/fields/select_field.rb``` で定義した ```choices``` を早速使う。


#### 追加したカスタムフィールドを使う

Dashboardの ```ATTRIBUTE_TYPES``` に定義を加える。

例： User モデルの gender をセレクトボックスで選択可に。

``` app/models/user.rb
class User < ActiveRecord::Base
  # ...
  GENDERS = %w(male female).freeze
  validates :gender, inclusion: { in: GENDERS }, allow_blank: true
end
```

性別は未記入を許したいので、 ```with_blank: true``` を活用！

``` app/dashboards/user.rb
  ATTRIBUTE_TYPES = {
    # All your other fields
    gender: SelectField.with_options(choices: User::GENDERS, with_blank: true),
  }
  
  FORM_ATTRIBUTES = [
    # Other form fields
    :gender
  ]
```

#### <i class="fa fa-exclamation-triangle"></i> 注意！！ 

Dashboard の属性定義時に、 ```SelectField``` で始める（namespace無し）ことに注意。
デフォルトで用意されている項目は

```
  ATTRIBUTE_TYPES = {
    #...
    name: Field::String,
  }
```

のように ``` Field::String ``` なのに対し、自分でカスタムフィールドとして作成した方は ``` gender: SelectField ``` のような感じになる。（namespace無し）

コピペして、 ```Field::SelectField ``` とやろうとすると、定義されてない旨表示されて悲しい思いをする。。。

（ここまで v.0.1.5以降なら不要）
- - -


## パスワードフィールド

現在パスワードフィールドもない。
が、githubで調べてみると、プルリクが上がっているのを発見。

- [create a password field by acrogenesis · Pull Request #325 · thoughtbot/administrate](https://github.com/thoughtbot/administrate/pull/325) 

もうすぐマージされそうなので（2016/02/25時点)そのうちデフォルトで入ってきそうな感じではある。

が、まだ入ってきてないので、先ほどと同じくカスタムフィールドで作ってみる。

### やってみる

#### generator 実行

ターミナルで以下を実行。

```
> rails generate administrate:field password
```

ファイルが生成されます。

- app/fields/password_field.rb
- app/views/fields/password_field/_show.html.erb
- app/views/fields/password_field/_index.html.erb
- app/views/fields/password_field/_form.html.erb

#### 必要な変更を加える

```app/fields/password_field.rb
require "administrate/fields/base"

class PasswordField < Administrate::Field::Base
  def to_s
    data
  end

  # 追加
  def truncate
    pretty_data.to_s[0...6]
  end

  # 追加
  def pretty_data
    data.gsub(/./, "•") unless data.nil?
  end
end
```

password fieldについてのプルリクで追加されているコードを丸コピっている。
今回は form にだけじゃなく、show, index でもパスワードのマスク表示するために上記2メソッドの追加。

#### ビュー

```app/views/fields/password_field/_index.html.erb
<%= field.truncate %>
```

```app/views/fields/password_field/_show.html.erb
<%= field.truncate %>
```

```app/views/fields/password_field/_form.html.erb
<div class="field-unit__label">
  <%= f.label field.attribute %>
</div>
<div class="field-unit__field">
  <%= f.password_field field.attribute %>
</div>
```

#### Dashboard

``` app/dashboards/user.rb
  ATTRIBUTE_TYPES = {
    # ...
    password: PasswordField,
    password_confirmation: PasswordField,
  }
```

## 日本語のローカライズ

Rails のロケールを ja にしてると、こんな変な表示になる場合がある。

![image](https://qiita-image-store.s3.amazonaws.com/0/5691/676defd0-2f79-d658-26a1-403fa823f0ce.png)

本来 Delete と表示される箇所に、ローカライズのエラーが出てる状態。

ブラウザの Elements で確認してみると、こんな感じ。

```
<a class="table__action--destroy" data-confirm="<span class=" translation_missing"="" title="translation missing: ja.administrate.actions.confirm">Confirm" rel="nofollow" data-method="delete" href="/admin/customers/1"&gt;<span class="translation_missing" title="translation missing: ja.administrate.actions.destroy">Destroy</span></a>
```

```translation_missing``` とあるので、翻訳失敗とわかる。

- [Japanese locales by k-motoyan · Pull Request #370 · thoughtbot/administrate](https://github.com/thoughtbot/administrate/pull/370)

すでにプルリク作ってる人がいるので、そのうちupdateに入ってくるんだけど・・
今回は対応前なので、自分で ```config/locales/administrate.ja.yml``` に必要なファイルを入れてみた。

## 最後に

基本的なカスタマイズの方法はこんな感じ。
どうでしょうか・・カスタマイズ・・やりやすい？のかな・・？

合わせてよく知らないgemの情報を探る方法も書いてみました。
対象が新しいgemとはいえ有名な thoughtbot のものなので、issues や サンプルコードの情報が全てGithub上に詰まっていて、かなり探しやすいgemだったのではないかなーと思います。
日本語解説記事のないgemを使ったのが初めてだったので、色々勉強になりました。