[学習用]Rails5でマイページ相当にユーザーアバター(画像)を表示できる様に実装する

![Firefox_Screenshot_2019-05-24T07-08-32.813Z.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132580/b1e4627a-089c-963d-cad2-a2484e639559.png)


Devise Userまでインストールしていることが前提
- gem 'devise'
- gem 'devise-i18n'
- gem 'devise-i18n-views'

```
$ bundle
$ rails g devise:install
$ rails g devise user
$ rails g devise:controllers users
$ rails g devise:i18n:views user
```
前提終わり

# 名前欄と画像欄を追加する
```
$ rails g migration AddNameToUsers name:string
$ rails g migration AddAvatarToUsers avatar:string
$ rails g uploader Avatar
$ rails db:migrate
```

# controllerに追加する
```app/controllers/application_controller.rb
  before_action :configure_permitted_parameters, if: :devise_controller?
  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:avatar, :avatar_cache, :remove_avatar])
  end
```

他のサイトでは、user_controller.rbに入れていたけど、それだと動かなかった。


# userと関連付け
```app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  # ユーザー画像を関連付け
  mount_uploader :avatar, AvatarUploader
end
```


# uploaderの設定
```app/uploader/avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  if Rails.env.development?
    # ローカルに保存する
    storage :file
  elsif Rails.env.test?
    # ローカルに保存する
    storage :file
  else
    # S3などの外部に保存する
    storage :fog
  end

  # S3のディレクトリ名
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # 許可する画像の拡張子
  def extension_whitelist
    %w(jpg jpeg gif png)
  end

  # 画像名をリネームさせる(日付時間はダメ絶対)
  def filename
    "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected
  # 一意となるトークンを作成
  def secure_token
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
  end

  # 画像サムネイル
  version :thumb do
    process resize_to_fill: [316, 316]
  end

  # アップロードの時点で指定サイズに収まるようにしておく
  process :resize_to_limit => [700, 700]

end


```

# ユーザー編集画面に追加
```app/users/registrations/edit.html.erb
    <div class="field">
      <% if current_user.persisted? && current_user.avatar? %>
        <%= image_tag(current_user.avatar.to_s, :class => "img-fluid", :alt => "ユーザーアバター") %>
        <label><%= f.check_box :remove_avatar %> 画像を削除</label>
      <% else %>
        <%= image_tag("favicon.png", :class => "img-thumbnail", :size => "230x230", :alt => "アイコン") %>
        <%= f.hidden_field :avatar_cache %>
      <% end %>

      <div class="input-group input-group-sm mb-3">
        <div class="input-group-prepend">
          <span class="input-group-text">アップロード</span>
        </div>
        <div class="custom-file">
          <%= f.file_field :avatar, class: 'custom-file-input' %>
          <label class="custom-file-label" for="customFile" data-browse="参照">ファイル選択...</label>
        </div>
      </div>
    </div>

```

user show.html.erbを作っておけばユーザー詳細画面にも表示できる。
Bootstrap4を入れておけば、デザインも楽です。