Controller actions permisson specs I'm just starting with rails and testing, and not sure what's good way to dry code like this.

require 'rails_helper'

describe EventsController, type: :controller do
  let(:admin) { create(:user_admin) }
  let(:mod) { create(:user_moderator) }
  let(:user) { create(:user) }

  let(:link) { create(:link) }
  let(:event) { create(:event) }

  describe 'GET #new' do
    it 'allows admin user to perform action' do
      sign_in admin

      get :new, link: link.id

      expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
    end

    it 'allows mod user to perform action' do
      sign_in mod

      get :new, link: link.id

      expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
    end

    it 'does not allow regular user to perform action' do
      sign_in user

      get :new, link: link.id

      expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
    end

    it 'does not allow guest to perform action' do
      get :new, link: link.id

      expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
    end
  end

  describe 'POST #create' do
    it 'allows admin user to perform action' do
      sign_in admin

      post :create, event: attributes_for_event(event, link)

      expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
    end

    it 'allows mod user to perform action' do
      sign_in mod

      post :create, event: attributes_for_event(event, link)

      expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
    end

    it 'does not allow regular user to perform action' do
      sign_in user

      post :create, event: attributes_for_event(event, link)

      expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
    end

    it 'does not allow guest to perform action' do
      post :create, event: attributes_for_event(event, link)

      expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
    end
  end
end
You could DRY the specs in the following way:


perform the authentication of the user in a before block
when testing a controller the subject could be the request itself
use context blocks for better structure
use functions for making the assertions when it comes to flash messages


So, keeping these in mind, you could write your specs like this:

require 'rails_helper'

describe EventsController, type: :controller do
  let(:link) { create(:link) }
  let(:event) { create(:event) }
  let(:admin) { create(:user_admin) }
  let(:moderator) { create(:user_moderator) }
  let(:user) { create(:user) }

  AUTHORIZATION_ERROR = /^You are not authorized to perform this action/

  describe 'GET #new' do
    subject { get :new, link: link.id  }

    before(:each) do
      sign_in(authorized_resource) if authorized_resource.present?
    end

    context 'for user with admin role' do
      let(:authorized_resource) { admin }
      it 'does not display an alert' do
        subject
        expect(flash[:alert]).to_not match(AUTHORIZATION_ERROR)
      end
    end

    context 'for user with moderator role' do
      let(:authorized_resource) { moderator }
      it 'does not display an alert' do
        subject
        expect(flash[:alert]).to_not match(AUTHORIZATION_ERROR)
      end
    end

    context 'for user with no role' do
      let(:authorized_resource) { user }
      it 'displays an alert' do
        subject
        expect(flash[:alert]).to match(AUTHORIZATION_ERROR)
      end
    end

    context 'for guest user' do
      it 'displays an alert' do
        subject
        expect(flash[:alert]).to match(AUTHORIZATION_ERROR)
      end
    end
  end
end


It might make sense to check for response codes as well (e.g. 401 Unauthorized, 403 Forbidden, etc) since a flash message on its own does say much about what's going on with the controller.