[rspec-users] Make macros DRY

David Chelimsky dchelimsky at gmail.com
Tue Dec 21 21:03:16 EST 2010


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-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

Cheers,
David





More information about the rspec-users mailing list