devise実装後のユーザ権限設定方法について記述していきます。

<h1>はじめに</h1>
前回の投稿では、アルバムページの作成方法についてご紹介いたしました。
その後、私はdeviseを使用してログイン機能の追加や各種投稿機能を実装し、
Railsアプリっぽくなってきた事に満足していたのですが、
重要な欠陥に気付きました。

それは、このままではどのユーザでログインしても投稿画面やアルバム一覧が全て見えてしまうという事です。。。。
絶対嫌ですよね。見知らぬ方にプライベートな写真や投稿を見られるのは。
このままではいけないと思い、各ユーザ毎に閲覧可能なページの権限設定方法について調べ、
実装しましたので備忘録として記事に残したいと思います。

下記の動画を参考にしました。非常に分かりやすくおすすめです。
お困りの方は是非ご覧いただければと思います。
https://www.youtube.com/watch?v=1bOhcNLkmec&t=579s

<h1>やりたいこと</h1>
UploadモデルをUserモデル(deviseにて作成)に紐付け、権限設定を行う

<h1>環境</h1>
macOS:10.15.2
Ruby:2.6.5
Rails:5.2.4.1
deviseインストール済み

<h1>手順</h1>
<h3>1. UploadモデルとUserモデルを紐付ける。</h3>

まずは、UploadモデルとUserモデルの紐付けを行う為に、マイグレーションファイルを用意します。
※今回は新規モデル作成ではなく、既存モデルの紐付けの為、追加という形になります。
※新規にモデルを追加される方は下記コマンドで関連づけるモデルを作成いただければと思います。
"rails g model モデル名(単数形) user:references name:string"
■以下コマンドの実行

```
$　rails g migration add_user_id_to_uploads user:references
```
すると次のようにマイグレーションファイルが作成されます。

``` Rails:add_user_id_to_uploads.rb
class AddUserIdToUploads < ActiveRecord::Migration[5.2]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end
```
問題なく、作成されていたら、"rails db:migrate"を実行してください。
これでUploadモデルとUserモデルがuser_idカラムを通じて紐付いた関係となりました。
次にmodelの編集を行います。

``` Rails:upload.rb
class Upload < ApplicationRecord
  belongs_to :user　　<!--追記-->
  mount_uploader :image, ImagesUploader
  validates :title, presence: true
  validates :image, presence: true
  validates :body, presence: true
end
```

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

  has_many :uploads, dependent: :destroy　　<!--追記-->
end
```
こちらの記述でUserを消すと紐づいているUploadモデルのデータも削除されるようになります。

<h3>2. 権限設定を行う</h3>
deviseにはログインしていない場合、トップ画面に戻すという機能がデフォルトで実装されています。
その機能を実装したいControllerの上部に下記記述をしてください。

``` Rails:uploads_controller.rb
class UploadsController < ApplicationController
  before_action :authenticate_user!　　<!--追記-->

　　　　　　　　　　　　　<以下省略>
```
これで、ログインしていないとアルバムページにアクセス出来なくなりました。

次にAのユーザが投稿したアルバムはAしか閲覧が出来ないという設定をコントローラに記述していきます。

``` Rails:uploads_controller.rb
class UploadsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_upload, only: [:show, :edit, :update, :destroy]
  before_action :validate_user, only: [:show, :edit, :update, :destroy]　
<!--追記　下部のprivateメソッドの内容をshow, edit, update, destroyに反映させます。-->

def index
　@uploads = current_user.uploads.order(created_at: :desc)
end
<!--こちらの記述により、一覧画面ではAが投稿したデータはAにしか表示されなくなります。-->

def show
end

def new
　@upload = Upload.new
end

def edit
end

def create
　@upload = Upload.new(upload_params)
　@upload.user_id = current_user.id　　
<!--作成した画像にuser_idを持たせ、current_user.idと結びつけます-->
   respond_to do |format|
   if @upload.save
　　　format.html { redirect_to @upload, notice: 'Upload was successfully created.' }
　　　format.json { render :show, status: :created, location: @upload }
   else
　　　format.html { render :new }
　　　format.json { render json: @upload.errors, status: :unprocessable_entity }
   end
   end
end
　　　　　　　　　　　　　<以下省略>

private
　def set_upload
　　@upload = Upload.find(params[:id])
　end

　def upload_params
　　params.require(:upload).permit(:image, :title, :body)
　end

  def validate_user
    if @upload.user != current_user
      redirect_to uploads_path, alert: "自分の投稿ではありません"
    end
  end
<!--こちらのvalidate_userの記述でURLからの不正アクセスを拒否します。-->
end
　　　　　　　　　　　　　
```
以上で、記述は終了となります。

<h1>まとめ</h1>
1.Userモデルと各種モデルを紐付ける(今回はUploadモデルが例でしたが、他投稿機能などがあれば、それに使用しているモデルも紐づける)
2.紐付け後にコントローラ側でアクセス権限を設定する

権限設定はもっと複雑な記述が必要になると思いましたので、
意外とシンプルな形で実装出来て驚きました。
是非お困りの方は参考にしていただければと思います。