Skip to content

Instantly share code, notes, and snippets.

@svs
Created October 5, 2012 06:05
Show Gist options
  • Save svs/3838340 to your computer and use it in GitHub Desktop.
Save svs/3838340 to your computer and use it in GitHub Desktop.
authorised_index
shared_examples "authorised index" do |user, items|
describe "index" do
before :each do
@request.env["devise.mapping"] = Devise.mappings[:user]
sign_in user
get :index
end
it "should assign proper items" do
assigns[:items].to_a.should =~ items
end
it "should respond ok" do
response.should be_ok
end
end
end
describe ItemsController
context "authorised" do
describe "index" do
Item.all.destroy!
@u = FactoryGirl.create(:user)
@admin = FactoryGirl.create(:admin)
@tagger = FactoryGirl.create(:tagger)
@i = FactoryGirl.create(:item, :user => @u)
@i2 = FactoryGirl.create(:item, :taggable => true)
it_behaves_like "authorised index", @u, [@i]
it_behaves_like "authorised index", @admin, Item.all.to_a
it_behaves_like "authorised index", @tagger, [@i2]
end
end
end
@myronmarston
Copy link

I'd recommend against code like this:

      Item.all.destroy!
      @u = FactoryGirl.create(:user)
      @admin = FactoryGirl.create(:admin)
      @tagger = FactoryGirl.create(:tagger)
      @i = FactoryGirl.create(:item, :user => @u)
      @i2 = FactoryGirl.create(:item, :taggable => true)

      it_behaves_like "authorised index", @u, [@i]
      it_behaves_like "authorised index", @admin, Item.all.to_a
      it_behaves_like "authorised index", @tagger, [@i2]

The problem is that the records are being created when the examples are being defined, which may happen long before the examples are actually run. Furthermore, the records are being created outside of the usual transaction management...which may leave your DB in an inconsistent state, and which may cause the records to no longer be there when the examples do run. Finally, the time it takes to create these records won't be reflected in the times rspec reports since it does it based on the time it takes each example to run.

Instead, you can pass a block to it_behaves_like and expose the records via let:

describe ItemsController
  context "authorised" do
    describe "index" do
      it_behaves_like "authorised index" do
        let(:user) { FactoryGirl.create(:user) }
        let(:items) { [FactoryGirl.create(:item, :user => user)] }
      end

      it_behaves_like "authorised index" do
        let(:user) { FactoryGirl.create(:admin) }
        let(:items) { [FactoryGirl.create(:item, :user => user), FactoryGirl.create(:item, :taggable => true)] }
      end

      it_behaves_like "authorised index" do
        let(:user) { FactoryGirl.create(:tagger) }
        let(:items) { [FactoryGirl.create(:item, :taggable => true)] }
      end
    end 
  end
end

Passing arguments to it_behaves_like works great for static values like strings, symbols and numbers, but not so great for database records that are in a global resource modified by many tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment