【Rails備忘録】deviseまとめ

# この記事について

deviseはRailsでユーザー認証を扱うときに非常に便利なgemです
初めて自分でDevise使ってユーザー認証周りを作ったので、その際に調べたこと・試したことなどを備忘録的に残しておきます
今回の使用したdeviseのバージョンは`v4.2.0`です

# gemのインストール

Gemfileに以下を追記して`bundle install`を実行

```rb
gem 'devise'
```

# 設定ファイルなどの生成

`rails g devise:install`で設定ファイルやViewで用いられるlocaleファイルが生成されます

以下は生成されたファイル

* config/initializers/devise.rb (設定ファイル)
  * パッと見変更しそうなものは2つぐらい
  * config.mailer_sender(送信元のアドレス)
  * config.password_length(パスワードの長さ, デフォルトは6文字以上128文字以下)
* config/locales/devise.en.yml (localeファイル)
  * 日本語のlocaleファイルの追加方法は後ほど詳述
* config/environments/development.rb (登録周りで飛ぶメールのホスト指定が追記される)
  * `config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }`が追記される

# ユーザーモデルの生成

`rails g devise Model`でモデルやマイグレーションが生成されます
Modelの部分にはUserやAdminなどが入るものと思ってください
以下は`rails g devise User`で生成されたファイル

* app/models/user.rb
* config/routes.rb
* db/migrate/20170211042541_devise_create_users.rb
* test/fixtures/users.yml
* test/models/user_test.rb

generateコマンドで生成された段階ではモデルは以下のようになっています

```rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
```

見て分かる通りデフォルトでは以下の機能が有効となっています

| module                   | 機能                                       |
|--------------------------|--------------------------------------------|
| database_authenticatable | DBに保存するパスワードの暗号化(必須)       |
| registerable             | サインアップ処理                           |
| recoverable              | パスワードリセット                         |
| rememberable             | クッキーにログイン情報を保持               |
| trackable                | サインイン回数・時刻・IPアドレスを保存     |
| validatable              | メールアドレスとパスワードのバリデーション |

また、コメントにある通り以下の機能を利用したい場合はモジュール名の追記が必要となります
その場合、マイグレーションにも対応するコメントアウトがあるのでそちらもコメントインしましょう
特にconfirmableあたりはよく使うことになると思うので注意が必要です

| module       | 機能                                           |
|--------------|------------------------------------------------|
| confirmable  | メール送信による登録確認                       |
| lockable     | 一定回数ログインに失敗した際のアカウントロック |
| timeoutable  | 一定時間でセッションを削除する                 |
| omniauthable | OmniAuthサポート                               |

モジュール追加の編集が終わったら`rake db:migrate`し、`/users/sign_up`にアクセスすればデフォルトの登録画面が表示されます

![WPCS2.png](https://qiita-image-store.s3.amazonaws.com/0/97367/2f714db5-d49f-5475-ef42-f3b3b3338d8b.png)


# View/Controllerのカスタマイズ

## Viewの生成

ここまでで認証自体は可能になりましたが、実際の開発で利用するにあたってはViewのカスタマイズが必要になると思います
`rails g devise:views Model`でModelに対応するViewが生成されます
以下は生成されたファイルです
これらのファイルをカスタマイズすればOKです

* app/views/users/confirmations/new.html.erb
* app/views/users/mailer/confirmation_instructions.html.erb
* app/views/users/mailer/password_change.html.erb
* app/views/users/mailer/reset_password_instructions.html.erb
* app/views/users/mailer/unlock_instructions.html.erb
* app/views/users/passwords/edit.html.erb
* app/views/users/passwords/new.html.erb
* app/views/users/registrations/edit.html.erb
* app/views/users/registrations/new.html.erb
* app/views/users/sessions/new.html.erb
* app/views/users/shared/_links.html.erb
* app/views/users/unlocks/new.html.erb

## Controllerの生成

コントローラーで行う処理を変更したい場合は`rails g devise:controllers Model`でControllerを生成することができます
以下は生成されたファイルです

* app/controllers/users/confirmations_controller.rb
* app/controllers/users/omniauth_callbacks_controller.rb
* app/controllers/users/passwords_controller.rb
* app/controllers/users/registrations_controller.rb
* app/controllers/users/sessions_controller.rb
* app/controllers/users/unlocks_controller.rb

この場合、生成されたControllerは`Devise::RegistrationController`などのコントローラーを継承する形になっており、デフォルトではすべてのメソッドが親クラスのメソッドを呼び出した状態でコメントアウトされています

```rb
class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  # def new
  #   super
  # end

  # ...
```

さらに、ルーティングを変更する必要があります
この例ではunlockとomniauthは利用してないのでルーティング変更してません

```rb
devise_for :users, controllers: {
  confirmations: 'users/confirmations',
  passwords:     'users/passwords',
  registrations: 'users/registrations',
  sessions:      'users/sessions',
}
```

これで、特定の条件下でのみconfirmationをスキップする、confirmation時に追加のユーザー情報を登録させるなどの細かな挙動のカスタマイズが可能になると思います(まだ試してないけど)

(参考)
[deviseでconfirmable設定をした際の確認メールをスキップさせる skip_confirmation! は、対象のオブジェクトをsaveする前に書く - Qiita](http://qiita.com/satomyumi/items/ff976c0a6ec2dae9814c)

# deviseのStrongParameterまわり

TODO: 余裕があれば後で書く

# deviseのi18n対応

今回作ったサイトでは日本語と英語に対応してほしいとの要望があったので、deviseのi18n対応についても簡単に調べてみました

deviseのWikiに各言語のロケールファイルの一覧が載っているのでこの中からおめあてのものを探しましょう
[I18n · plataformatec/devise Wiki](https://github.com/plataformatec/devise/wiki/I18n)

DLしたら`config/locale/devise.Lang.yml`にロケールファイルを置いてあげましょう
日本語の場合なら`config/locale/devise.ja.yml`です

すでにデフォルトのロケールが日本語になっていれば問題ないですが、そうでなければ`config/application.rb`の中でデフォルトのロケールを変更してあげましょう

```rb
module WPCS2
  class Application < Rails::Application
    # ...

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    config.i18n.default_locale = :ja 

    # ...
  end
end
```

これでエラーメッセージなどが日本語化されます
(一部、追加しないとtranslationに失敗する部分もあるようですが)

=== 2017/02/20追記 ===

ビューについては`devise-i18n`というgemがあるのでそちらを使いましょう
[tigrish/devise-i18n: Translations for the devise gem](https://github.com/tigrish/devise-i18n)

まずはGemfileに `gem devise-i18n` を追記してインストール
そして、viewを `rails g devise:i18n:views` で生成できます
生成されたビューは`app/views/devise` に置かれるので `app/views/users` などにリネームしましょう
これだけだとビューに書かれたパーシャルの描画指定などが矛盾してしまうので、 `render "devise/..."`と成っている部分のdeviseをusersに書き換えます
最後に `rails g devise:i18n:locale ja` などとしてロケールファイルを生成します
ロケールファイルの中を開いて、deviseとなっているところをusersに変えましょう

また、これだけだと一部のエラーメッセージなどがtranslation missingになってしまう場合があります
rails-i18nというリポジトリに汎用的に使えるロケールファイルのテンプレートがあるのでダウンロードして `config/locale/ja.yml` に配置しましょう
(まぁ、これはdeviseに限らずi18n対応するなら一番最初にやっておくべきことなのですが)
[svenfuchs/rails-i18n: Repository for collecting Locale data for Ruby on Rails I18n as well as other interesting, Rails related I18n stuff](https://github.com/svenfuchs/rails-i18n)

=== 追記終わり ===


# まとめ

deviseを使うことで非常に簡単にユーザー認証機能を作成できます
今回は試してないですが、OmniAuthまわりもサポートがあるようなので、TwitterやFacebookなどのアカウントでログインといった機能も簡単に実装できるようです(あんまりよくわかってないけど)
できれば、中でどんな処理を行っているのかも簡単に把握しておくといざというときも対処ができてよいかもしれません