[Rails] deviseとActiveStorageを用いたユーザー登録

#はじめに
deviseとActiveStorageを用いたユーザー登録を説明していきます。この記事は自分用の防備録として書いています

#1.アプリケーションの立ち上げ
```:ターミナル
$ rails new PlanDo
```

#2.deviseのインストール
```:Gemfile
$ gem 'devise'
```

Gemfileに記入した後は忘れずにbundle installを行ってください

```:ターミナル
$ bundle install
```

次にdeviseをインストールします

```:ターミナル
$ rails g devise:install
```
ここまでの作業でdeviseのinstallが完了しました

#ユーザー用のテーブルの作成(User)
```:ターミナル
$ rails g devise user
```
これでマイグレーションファイルがつくられたので次にrails db:migrateを行います

```:ターミナル
$ rails db:migrate
```

これでuserモデルができました。しかし今回はアカウントの登録時に名前をつけられるようにしたいのでUserモデルにnameカラムを追加します

#Userにnameカラムを追加する
すでにUserモデルは作成してあるので今回は今あるUserモデルにnameを追加するためにマイグレーションファイルを作成します

```:ターミナル
$ rails g migration AddNameToUsers name:string
```

マイグレーションファイルには命令規則があるのでそれをもとに名前をつけます

```
add_{追加するカラム名}_to_{カラムを追加するモデル名を複数形で}
```
そしたらrails db:migrateを行います

```:ターミナル
$ rails db:migrate
```
このままではnameはカラムには保存されないので保存できるようにいろいろと変更していきます

#nameを使えるようにする
strong parameterをapplication_controller.rbに追加する。

```ruby:controllers/appication_controller.rb
class ApplicationController < ActionController::Base

  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) # 新規登録時(sign_up時)にnameというキーのパラメーターを追加で許可する
  end
end
```
これでDBに反映されます
次にviewの編集を行います。ただし今回は日本語に対応させたいので設定を日本語に変えます

#deviseを日本語に設定

```:Gemfile
gem 'devise-i18n'
gem 'devise-i18n-views'
```
gemfileに上記の２点を加えます
その次にbundle installをします

```:ターミナル
$ bundle install
```

次にターミナルでviewを作成します。
日本語設定にするので devise:i18n:viewsを打ちます

```:ターミナル
$ rails g devise:i18n:views
```
続いて後にコントローラも使うのでそれも導入しておきます

```:ターミナル
$ rails g devise:controllers users
```

次にコントローラーを編集します

```ruby:routes.rb
devise_for :users, controllers: {
    registrations: 'users/registrations',
    sessions: 'users/sessions'
  }
```


続いて日本語訳の設定ファイルを（devise.views.ja.yml）を編集するため作成します

```:ターミナル
$ rails g devise:i18n:locale ja
```

このままではname属性が日本語に変わらないので日本語に設定しておきます

```ruby:config/locales/devise.views.ja.yml
ja:
  activerecord:
    attributes:
      user:
        confirmation_sent_at: パスワード確認送信時刻
        confirmation_token: パスワード確認用トークン
        confirmed_at: パスワード確認時刻
        created_at: 作成日
        current_password: 現在のパスワード
        current_sign_in_at: 現在のログイン時刻
        current_sign_in_ip: 現在のログインIPアドレス
        email: Eメール
        encrypted_password: 暗号化パスワード
        failed_attempts: 失敗したログイン試行回数
        last_sign_in_at: 最終ログイン時刻
        last_sign_in_ip: 最終ログインIPアドレス
        locked_at: ロック時刻
　　　　　#追加
        name: 名前

        password: パスワード
        password_confirmation: パスワード（確認用）
        remember_created_at: ログイン記憶時刻
        remember_me: ログインを記憶する
        reset_password_sent_at: パスワードリセット送信時刻
        reset_password_token: パスワードリセット用トークン
        sign_in_count: ログイン回数
        unconfirmed_email: 未確認Eメール
        unlock_token: ロック解除用トークン
        updated_at: 更新日
    models:
      user: ユーザー
~~以下省略
```


このままではデフォルトのEnが適用されてしまうので日本語に変えます

```ruby:config/application.rb
module PlanDo
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.1

    # Configuration for the application, engines, and railties goes here.
    これを追加
    config.i18n.default_locale = :ja
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")
  end
end
```

最後にサインイン時にnameを入力できるようにviewを変更します

```ruby:views/devise/registrations/new.html.erb
<h2><%= t('.sign_up') %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
  #追加
  <div class="field">
    <%= f.label :name %> <br />
    <%= f.text_field :name %>
  </div>
　#ここまで

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em><%= t('devise.shared.minimum_password_length', count: @minimum_password_length) %></em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit t('.sign_up') %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

```
これでログイン時に名前を入力でき、また日本語になったと思います。

#UserにActionStorageを用いて画像登録
始めにターミナルで以下のコマンドを打ってください

```:ターミナル
$ rails active_storage:install
$ rails db:migrate
```

これでActiveStorageを使う準備は整いました
次にUserモデルに画像を持つための変数を定義します

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

```
次にdeviseのstrong parametersにimageを追加します

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

  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) # 新規登録時(sign_up時)にnameというキーのパラメーターを追加で許可する
    devise_parameter_sanitizer.permit(:account_update, keys: [ :image])
  end

end

```
次にusers/registrations_controllerのupdateを編集し画像を受け取れるようにします

```ruby:users/registraions_controller.rb
def update
    super
    if account_update_params[:image].present?
      resource.image.attach(account_update_params[:image])
    end
  end
```
最後に画像を登録できるようにedit.html.erbを編集します

```ruby:views/devise/registrations/edit.html.erb
<h2><%= t('.title', resource: resource.model_name.human) %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div><%= t('.currently_waiting_confirmation_for_email', email: resource.unconfirmed_email) %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(<%= t('.leave_blank_if_you_don_t_want_to_change_it') %>)</i><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= t('devise.shared.minimum_password_length', count: @minimum_password_length) %></em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(<%= t('.we_need_your_current_password_to_confirm_your_changes') %>)</i><br />
    <%= f.password_field :current_password, autocomplete: "current-password" %>
  </div>
  #以下を追加
  <div class="field">
    <%= f.label :image %><br />
    <%= f.file_field:image %><br>
  </div>
　#ここまで
  <div class="actions">
    <%= f.submit t('.update') %>
  </div>
<% end %>

<h3><%= t('.cancel_my_account') %></h3>

<p><%= t('.unhappy') %> <%= button_to t('.cancel_my_account'), registration_path(resource_name), data: { confirm: t('.are_you_sure') }, method: :delete %></p>

<%= link_to t('devise.shared.links.back'), :back %>

```

これで画像も登録できるようになりました
最後にcontrollerを作り出力を見てみましょう
#home_controllerの作成
```:ターミナル
rails g controller home index
```

home_controllerとroutes.rbを編集します

```ruby:controllers/home_controller.rb
class HomeController < ApplicationController
  before_action :authenticate_user!

  def index
    @users = User.all
  end
end
```

```erb:views/home/index.html.erb
<% @users.each do |user| %>
  <%= user.name %>
  <% if user.image.attached? %>
    <%= image_tag user.image %>
  <% else %>
    <img src="<%= "/default_image.png" %>">
  <% end %>
<% end %>
```

最後にroutes.rbを変更します

```ruby:routes.rb
Rails.application.routes.draw do
  root 'home#index'
  devise_for :users, controllers: {
    registrations: 'users/registrations',
    sessions: 'users/sessions'
  }
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```


お疲れ様でした
以下のようにできれば成功です

```:ターミナル
$ rails s
```
![a2SIN20Bt5VR4Ad1617338658_1617338665.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268848/e7a704b1-4ca3-c869-71f9-635f5c7f5161.png)

新規登録しましたら
http://127.0.0.1:3000/users/edit
に移動して画像を保存します

![Nh297xD88RGhQuM1617338682_1617338692.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268848/de603e8a-05e0-09a6-297f-e797eb51ea9b.png)

最終的に自分の名前と保存した画像が表示されたら成功です

![VYNtSSURG8cwJiF1617338710_1617338718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268848/5bb05474-1dc8-0271-8fb4-51cfeb1f3423.png)

###参考にしたサイト
https://qiita.com/eitches/items/6f1d80b21287e09a7477

https://qiita.com/YUSUKE39/items/d8aedc0c3a3017b36691

https://qiita.com/you8/items/921e0dd1210eb0d158df

https://qiita.com/koki_73/items/86e5808e7dae78c3c564#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB