punditのtest

pundit使うので、role-abilityのtable構成はhttp://magazine.rubyist.net/?0047-IntroductionToPunditを参考にしたというかそのまま。

とりあえずusersのindexを、adminのみ見れて、normalなuserは見れないのを試す。

userのindexにauthorize @usersを入れておいてusers_policyに飛ばす。users_policyではcan?(__method__)して、action名教えてあげる。can?は別のところでも使いたいのでapplication_policyで。

def can?(action)
    action = action.to_s.chop
    user.abilities.exists?(domain: record.class.to_s.split("::").first.underscore, ability: action)
end

recordは@usersが入っているので、そこからnamespaceだけ取り出す。abilityはusers_policyから貰ったaction名を?は要らないので外して探す。

テスト側ではabilities.ymlに権限入れておく、これをadminのみにつける

one:
  domain: user
  ability: index

role_flows_test.rbで、まずsnsで認証通してuser作成する。

class ActorFlowsTest < ActionDispatch::IntegrationTest
    setup do
        get "/auth/twitter/callback"
        @user = SocialProfile.find_by(uid: "123545").user
    end

    def set_user
        @user.role = roles(:two)
        @user.save
    end

    def set_admin
        @user.role = roles(:one)
        @user.role.abilities << abilities(:one)
        @user.save
    end

    test "index by admin user" do
        set_admin
        get users_path 
        assert_response :success
    end

    test "index by user" do
        set_user
        assert_raise(Pundit::NotAuthorizedError) do
            get users_path 
        end
    end
end

adminなuserはindex見た時にsuccessはok。

問題はnormalなuserで、indexが見れちゃいけない。indexにget飛ばした時に、500-599とか返さないで例外出してしまう...。assert_responseは諦めて Pundit::NotAuthorizedErrorをcatchするように変更して通った。

これ全部につけるのか...。やっぱ辛ぇわ...。