[rspec-users] Make macros DRY

rejeep johan.rejeep at gmail.com
Wed Dec 22 05:11:21 EST 2010


Thanks for your reply David!

My solution ended up something like this:

  def it_should_grant_access(role, options)
    request_index = proc do
      get :index

      response.success?
    end

    # ...

    actions_from(options).each do |action|
      request = instance_eval(&eval("request_#{action}"))
      request.should be_true, "#{role} should have been granted access
to #{action}, but was not"
    end

    # ...
  end

Not perfect, but it works.

Btw, I solved the "not-case" by flipping only and except and then just
call it_should_grant_access.

Thanks!

On Dec 22, 3:03 am, David Chelimsky <dchelim... at gmail.com> wrote:
> On Dec 21, 2010, at 2:11 PM, rejeep wrote:
>
>
>
>
>
>
>
>
>
> > Hey,
>
> > I have lots of problems to refactor RSpec macros and make them DRY.
> > Right now I'm stuck in such a situation for some role macros.
>
> > In my controller tests, I want to write:
>
> >  1) it_should_grant_access(:super_admin, :to => :countries)
> >  2) it_should_grant_access(:admin, :to => :countries, :only =>
> > [:index, :show])
> >  3) it_should_not_grant_access(:user, :to => :countries)
>
> > These three rules should make sure that:
>
> >  1) Super admin should be granted access to all default actions in
> > the countries controller
> >  2) Admin should be granted access to index and show, but not to new,
> > create, edit, update or destroy
> >  3) User should not be granted access to any of the default actions
>
> > Since I want to be using this from many places, I used a module:
>
> >  module RoleMacros
> >    DEFAULT_ACTIONS =
> > [:index, :show, :new, :create, :edit, :update, :destroy]
>
> >    def it_should_grant_access(role, options)
>
> >      # ...
>
> >      if except.present?
> >        actions = DEFAULT_ACTIONS - Array(except)
> >      elsif only.present?
> >        actions = Array(only)
> >      else
> >        actions = DEFAULT_ACTIONS
> >      end
>
> >      # ...
>
> >    end
>
> >    def it_not_should_grant_access(role, options)
> >      # ...
> >    end
> >  end
>
> > As you see from the example code there are some stuff I need to do
> > before I can do the actual testing.
>
> > My question is how to solve this in a DRY way so that I can use the
> > set up code in the "not" case as well?
>
> Just use the Extract Method refactoring:
>
> def it_should_grant_access(role, options)
>   actions_from(options).each do |action|
>     # ...
>   end
> end
>
> def it_not_should_grant_access(role, options)
>   actions_from(options).each do |action|
>     # ...
>   end
> end
>
> def actions_from(options)
>   if options[:except]
>     DEFAULT_ACTIONS - options[:except]
>   elsif options[:only]
>     options[:only]
>   else
>     DEFAULT_ACTIONS
>   end
> end
>
> > Another problem is that when I specify that some role should have
> > access to some actions, it also means that the role should not have
> > access to all but those actions. This means that I must have each
> > request test in separate so that I can call them. But I'm not sure how
> > to do this.
>
> Just use one macro:
>
> def it_should_grant_access(role, options)
>   actions_from(options).each do |action|
>     # ... specify grant access
>   end
>   (DEFAULT_ACTIONS - actions_from(options)).each do |action|
>     # ... specify deny access
>   end
> end
>
> HTH,
> David
>
> > Thanks!
> > _______________________________________________
> > rspec-users mailing list
> > rspec-us... at rubyforge.org
> >http://rubyforge.org/mailman/listinfo/rspec-users
>
> Cheers,
> David
>
> _______________________________________________
> rspec-users mailing list
> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users


More information about the rspec-users mailing list