rails5にsorceryを導入

rails5で登録機能・ログイン機能を実装途中。
とりあえずやったことをまとめた。

## 大枠

### まずはgemを入れて `bundle install` する

```ruby:gemfile
gem 'sorcery'
```


### 次にsorceryをinstallする userテーブルが生成される

```ruby
rails g sorcery:install
```
※カラムの追加が必要な場合は適宜行う。
私はもともとuserテーブルを作ってしまっていたため、sorceryを導入する際に、rollbackを行なった。

migrationを行なって、userテーブルを作成する。

```ruby
rake db:migrate
```

### user.rbに下記を記載する。

```ruby:user.rb
class User < ApplicationRecord
  authenticates_with_sorcery!
  validates :password, confirmation: true
  validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }
```

## User登録

### user登録フォーム
なんの変哲も無いフォーム

```ruby:new.html.erb
<h2> ユーザー登録 </h2>
<%= form_with model: @user, local: true do |f| %>
  <div class="field">
    <%= f.label :name %><br />
      <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
      <%= f.email_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %><br />
      <%= f.password_field :password %>
  </div>
  <div class="field">
    <%= f.label :password確認 %><br />
      <%= f.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <%= f.submit "登録" %>
  </div>
<% end %>
```

### コントローラーの記述
password_confirmationはsorceryが提供してくれる modelの `attributes` ？？
user.rbの `validates` で `validates :password, confirmation: true` と記載しないと、

```:pry
[6] pry(main)> User.instance_methods.grep(:password)
=> [:password]
[7] pry(main)> User.instance_methods.grep(:password_confirmation)
=> []
```
のように、Usermodelで使用しようとすると、NoMethodErrorになってしまう。
記載すると、

```
[9] pry(main)> User.instance_methods.grep(:password_confirmation)
=> [:password_confirmation]
```
こうなる（╹◡╹）


user.createする。これでUserが作れました！

```ruby:users_controller.rb
class UsersController < ApplicationController
  #ログインをしていなかった場合、指定のページに飛ばすbefore_actionをskipするため。
  skip_before_action :require_login, only:[:new, :create]

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to mypage_path
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(
      :name,
      :email,
      :password,
      :password_confirmation
    )
  end
end
```

## ログインする

ログイン画面のviewを作成(割愛)

### sessions_controllerを作成

```ruby:sessions_controller.rb
class SessionsController < ApplicationController
  skip_before_action :require_login, except: [:destroy]

  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_back_or_to(mypage_path, notice: 'login successful!')
    else
      flash.now[:alert] = 'login failed'
      render :new
    end
  end

  def destroy
    logout
    redirect_to root_path
  end
end
```

### 認証済みの確認
application_controllerに以下のように記載する。

```ruby:application_controller.rb
class ApplicationController < ActionController::Base
  before_action :require_login

  protected

  def not_authenticated
    redirect_to sign_in_path
  end
end
```

`before_action :require_login` これは、sorceryの内部実装で定義してあり、ログインしているかどうかを判断し、`not_authenticated` で定義してあるリダイレクト先に飛ばす処理が走る。
これを適用したくないアクションには、`skip_before_action` で指定する必要がある。

**ちなみに`skip_before_action` はrails5から。rails4までは `skip_before_filter` が推奨されていた。**


### これからログイン周りでやること
- [ ]  User登録後ログイン画面にリダイレクトするのではなく、登録＝ログインの状態にしたい
- [ ]  退会処理
- [ ]  SNSログイン

### これから調べること

Active Modelについて(https://railsguides.jp/active_model_basics.html)
=> modelのattributesのerrorが出た時にわからなかったため。

protectedについて(http://rochefort.hatenablog.com/entry/effective_ruby_section14_protected)
=> `private` はよく使用するが、`protected`の用途がよくわかっていない。調べたい。