RailsAdminを使ってみた

[ウェブクルー Advent Calendar 2017](https://qiita.com/advent-calendar/2017/webcrew) 20日目の記事です！
昨日は@wc_orks さんの「[正規表現で置換時にマッチした文字をそのまま使う](https://qiita.com/wc_orks/items/403809e4a45349799e3e)」でした！

# RailsAdminとは
* 管理画面を簡単に実現する事ができるgem
* [デモサイトはこちら](http://rails-admin-tb.herokuapp.com/)
* 使うまでの楽さ:smiley:
* 導入時点での機能:smiley:
* カスタマイズのしやすさ:thinking: 

# Gemなどのバージョン
* ruby 2.3
* rails 5.1.4
* mysql 5.7
* rails_admin 1.2
* device 4.3
* cancan 2.1.2

dockerを使ってrailsプロジェクトを作成しています。
詳細は割愛させていただきますが、
記事の最後にgithubのリンクを貼っておくので、よろしければご覧ください。

# 導入
## RailsAdminのインストール
```
rails g rails_admin:install
```

## device設定
ユーザ管理にdeviceを利用するので設定を行います。
利用する機能はデフォルトのまま進めます。

```
rails g devise:install
```

メッセージが色々出るので、案内通りに設定します。
config/environments/development.rbに以下を設定

```
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```

Pagesコントローラの作成

```
rails g controller Pages index show
```

/config/routes.rbに以下を追加

```
root to: "home#index"
```

app/views/layouts/application.html.erbに以下を追加

```
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
```

deviseを使ってviewやmodelを作成

```
rails g devise:views
rails g devise User
rails db:migrate
```

## cancan
abilityの追加

```
rails g cancan:ability
```

usersテーブルにadmin列を追加

```
rails g migration AddColumnAdminToUser admin:boolean
rails db:migrate
```
users.adminに1をセット(SQLのupdate等で更新する）

```
UPDATE users SET admin=1;
```

models/ability.rbの以下をコメント外す

```
user ||= User.new # guest user (not logged in)
if user.admin?
    can :manage, :all
else
    can :read, :all
end
```

ここまでうまくできていれば以下の確認ができます。

* ルートへのアクセス(localhost:3000)
* /adminにアクセスしようとするとログイン画面が表示され、Sign Upボタン押下でユーザ登録が可能


# 少しカスタマイズしてみる
## 権限設定を行う
権限テーブル追加して、ability.rbで表示画面、実行可能アクションの制限 
 
```
rails g model Role name:string
rails g migration AddColumnRoleToUser role_id:integer
```

models/user.rbに以下のようにbelongs_toでアソシエーションを追加

```
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  belongs_to :role
end
```
models/role.rbに以下のようにhas_manyでアソシエーションを追加

```
class Role < ApplicationRecord
    has_many :users
end
```

変更の反映

```
rails db:migrate
rails restart
```

以下のようにRolesにデータを追加

```
INSERT INTO `roles` (`id`, `name`, `created_at`, `updated_at`)
VALUES
	(1,'admin','2017-12-14 14:42:06','2017-12-14 14:42:06'),
	(2,'manager','2017-12-14 14:42:14','2017-12-14 14:42:14'),
	(3,'leader','2017-12-14 14:42:30','2017-12-14 14:42:30'),
	(4,'developer','2017-12-14 14:42:45','2017-12-14 14:42:45');
```

ついでにusersの更新も行う

```
UPDATE users SET role_id = 3;
```

特定のテーブルの参照/更新権限などの確認を行うため、
適当にテーブルを追加

```
rails g model item name:string price:integer 
rails db:migrate
rails restart
```

データをこんな感じで入れておきましょう。

```
INSERT INTO `items` (`id`, `name`, `price`, `created_at`, `updated_at`)
VALUES
	(1,'ビール',500,'2017-12-14 14:59:20','2017-12-14 14:59:28');
```

それでは実際に権限設定を行っていきます。

models/ability.rbを以下のように設定

``` 
class Ability
  include CanCan::Ability

  def initialize(user)
      if user
        can :access, :rails_admin
        can :dashboard, :all
      end
      if user.admin?
        can :manage, :all
      end

      if user.role_id == 2
        can [:read,:new,:update,:create,:export,:import], [Item]
      end
      if user.role_id == 3
        can [:read,:new,:update,:create], [Item]
      end
      if user.role_id == 4
        can [:read], [Item]
      end
    
  end
end
```

ここまで行えば、ユーザの権限に対する画面表示等が可能となります。

## 日本語化と表示項目の設定
### rails_admin.rbを使った日本語化
config.model 'ModelName' doで対象テーブルの項目表示設定を行います。
表示したい項目を設定していくやり方、include_all_fieldsで全ての項目を表示するやり方等があります。
この辺りは[wiki](https://github.com/sferik/rails_admin/wiki/Fields)に記載されています。

config/initializers/rails_admin.rb

``` 
RailsAdmin.config do |config|

    ## == Devise ==
    config.authenticate_with do
      warden.authenticate! scope: :user
    end
    config.current_user_method(&:current_user)
  
    ## == Cancan ==
    config.authorize_with :cancan
  
    config.actions do
      dashboard                     # mandatory
      index                         # mandatory
      new
      export
      bulk_delete
      show
      edit
      delete
      show_in_app
    end

    config.model 'User' do
      LABEL_id = 'ユーザID'
      LABEL_email = 'メールアドレス'
      LABEL_admin = '管理者フラグ'
      LABEL_role = '権限'
      LABEL_created_at = '作成日時'
      LABEL_updated_at = '更新日時'

      # ここに指定した項目が表示される。include_all_fieldsをすれば全て表示。
      list do
        field :id do
          label LABEL_id
        end
        field :email do
          label LABEL_email
        end
        field :admin do
          label LABEL_admin
        end
        include_fields :role do
          label LABEL_role
        end
        field :created_at do
          label LABEL_created_at
        end
        field :updated_at do
          label LABEL_updated_at
        end
      end
    end

    config.model 'Role' do
      LABEL_id = '権限ID'
      LABEL_name = '権限名'
      LABEL_created_at = '作成日時'
      LABEL_updated_at = '更新日時'
      list do
        field :id do
          label LABEL_id
        end
        field :name do
          label LABEL_name
        end
        field :created_at do
          label LABEL_created_at
        end
        field :updated_at do
          label LABEL_updated_at
        end
      end
      show do
        field :id do
          label LABEL_id
        end
        field :name do
          label LABEL_name
        end
        field :created_at do
          label LABEL_created_at
        end
        field :updated_at do
          label LABEL_updated_at
        end
      end
      create do
        field :name do
          label LABEL_name
          # helpを指定することにより、項目説明を入れることが可能
          help "最大文字数: 255"
        end
      end
      update do
        field :id do
          label LABEL_id
          read_only true
          help ""
        end
        field :name do
          label LABEL_name
          help "最大文字数: 255"
        end
      end
    end 
  end
```

上記に加えてusersのここまで設定できれば、ユーザの権限に対応する画面表示ができるようになります。


#### /locales/ja.ymlを使った共通項目の日本語化
* [wiki](https://github.com/sferik/rails_admin/wiki/Translations)のJapaneseのリンクから内容をコピーし、config/locales/ja.ymlを作成します
* config/application.rbに以下のコードを追加します

```
config.i18n.default_locale = :ja
```

## csvインポート機能の追加
Gemfileに以下を追加し、bundle install

```
gem "rails_admin_import", "~> 2.1"
```

rails_admin.rbのconfig.actionsにimportを追加

```
    config.actions do
      dashboard                     # mandatory
      index                         # mandatory
      new
      export
      bulk_delete
      show
      edit
      delete
      show_in_app
      # importを追加することにより、CSVインポートが可能となる
      import
    end
```





# まとめ
以上、RailsAdminの機能を使って管理ツールを作成してみました。
導入時点でCRUDとCSVダウンロード/アップロードの機能を使えるようになるため、
チーム内で利用する際には便利だと思います。
deviceとcancanを組み合わせる事によって認証機能を作れちゃうのも素晴らしいですね。

ただし画面構成を変えたり、RailsAdminが用意していない項目や機能を追加するならば、
ActiveAdminなど他のgemを利用した方が良いかもしれませんね。

明日の担当は@morotin さんです！よろしくお願いします！

# github  
https://github.com/da-shi/catchup/tree/master/RailsAdmin

# 参考にさせていただいたページ
[本家のWiki](https://github.com/sferik/rails_admin/wiki)
[[*Rails*] deviseの使い方（rails5版）](https://qiita.com/cigalecigales/items/f4274088f20832252374)