LoginSignup
1
2

More than 3 years have passed since last update.

Rails 6で認証認可入り掲示板APIを構築する #17 管理者権限の追加

Last updated at Posted at 2020-09-22

Rails 6で認証認可入り掲示板APIを構築する #16 policyの設定

管理者権限を用意する

前回までの実装で、投稿の編集や削除は投稿者本人だけできるようになりました。
ですがそこに拡張し、管理者としてログインしている時は誰の投稿でも編集・削除できるようにしてみます。

そのためにはuserモデルにadminカラムを追加しましょう。

$ rails g migration AddAdminToUsers admin:boolean
db/migrate/xxxxxxxxxxxxxx_add_admin_to_users.rb
# frozen_string_literal: true

class AddAdminToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :admin, :boolean, default: false, null: false
  end
end

さて、今までは機能を実装してからテストを書いていましたが、punditの基本挙動は理解できたと思うので、先にテストから書いてみます。

管理者権限のない別ユーザーでログインしていた際に編集削除できないテストはすでに書かれているので、

  • 管理者権限のある際に別ユーザーの投稿を編集できること
  • 管理者権限のある際に別ユーザーの投稿を削除できること

を実装してみます。
厳密にはpolicyテストとrequestテスト両方実装すると万全ですが、ここはpolicyだけ実装してみます。

もし良ければここから書いてあるサンプルを見ずに、まずは自力で実装してみて見比べてみると、コードを書く練習になるのでやってみてください。

post_policy_spec.rbの編集

spec/policies/post_policy_spec.rb
...
 RSpec.describe PostPolicy, type: :policy do
   let(:user) { create(:user) }
+  let(:admin_user) { create(:user, admin: true) }
   let(:post) { create(:post) }

...
     it "ログインしているが別ユーザーの時に不許可" do
       expect(subject).not_to permit(user, post)
     end
+    it "adminユーザーでログインしている時に許可" do
+      expect(subject).to permit(admin_user, post)
+    end
...
spec/factories/posts.rb
...
     remember_created_at { nil }
     name { "MyString" }
     tokens { nil }
+    admin { false }
   end
...

ここまで実装したらrubocopとrspecを動かして確認。
まだpolicyファイルを実装していないのでテストはコケます。

policyの実装

まずは管理者であることを判定するprivateメソッドをapplication_policy.rbに生やします。

app/policies/application_policy.rb
...
   private

   def mine?
     @record.user == @user
   end
+
+  def admin?
+    @user.present? && @user.admin?
+  end
+

あとはpost_policy.rbのupdate?destroy?の2つの判定を変えるだけですね。

app/policies/post_policy.rb
   def update?
-    mine?
+    mine? || admin?
   end

   def destroy?
-    mine?
+    mine? || admin?
   end

なんとこれだけです。

traitを使ってadminを簡単に作る

これだけだと少し中身の薄い記事なので、factoryBotを触ってadminユーザーをもっと簡単に作れるようにします。

spec/factories/users.rb
     name { "MyString" }
     tokens { nil }
     admin { false }
+
+    trait :admin do
+      admin { true }
+    end
   end
spec/policies/post_policy_spec.rb
 RSpec.describe PostPolicy, type: :policy do
   let(:user) { create(:user) }
-  let(:admin_user) { create(:user, admin: true) }
+  let(:admin_user) { create(:user, :admin) }
   let(:post) { create(:post) }

これでrspecを動かしてみるとどうでしょうか。
ミスなく書けていればテスト通過するはずです。

traitはご覧の通り、factoryBotのcreate等の第2引数に別名として渡すことで使うことができます。
adminフラグを立てるだけなら恩恵も少なく意味もあまりないのですが、例えばadminユーザーの場合に必ずセットで初期値を持っておきたいカラムがあったりすれば、いちいちcreateのたびに複数カラムの初期値セットをしなくて済みます。

ぜひご活用ください。

続き

Rails 6で認証認可入り掲示板APIを構築する #18・終 user controllerの実装
連載目次へ

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2