On 2011-01-21 10:25 PM, David K. wrote:
Hello all,
like to cover that failure somehow.
current_role = self.role.name <http://self.role.name/>
in to the system. If you are activating a new user please log out
I don't really like the idea of 'controllers' living inside a
invoked:
return_value = User.new.authorize(controller_name, action_name)
end
Keeping the “cup of tea” idea in mind, I can understand how you could
arrive at this point. I did something similar a couple of years ago. I
was passing something into the model that could come only from a
controller, which was fine and dandy until I needed to use the model
method in some way that proved difficult to get that information. It may
have been a rake task, I can’t remember the exact details. But from that
point, I started thinking about my models as separate from the
particular application I was working on at the moment. When creating
methods and passing in arguments, I started thinking about what would
happen if I used this model outside of the Rails application. Would I
still be able to pass that information in easily and would it make
sense?
The other thought that I had with this particular approach (passing
controller name and action into the model) is that it seems the model
specs would feel sort of fake. In order to unit test the authorize
method, you have to test with real values. I may be overlooking
something (just got up, so it’s very possible), but that doesn’t seem
like it’s testing behavior so much as how the method handles specific
values. If you add new controllers and/or actions, you must then go add
them to your unit test to make sure the authorize method responds
correctly. That doesn’t seem like the kind of test that I’d feel
comfortable trusting.
Now that I think about it, I actually had this same situation come up a
couple of years ago. Before I started splitting role-based functionality
into separate namespaced controllers, I was trying to control access to
various actions via before_filters. Using the same concept of
controller/action combination, I created a hash of those pairs and which
roles could access them. The role names then turned into model methods
that returned true/false. Something like:
access_rules = {
‘products’ => {
‘show’ => [:clerk, :manager],
‘new’ => [:manager],
‘edit’ => [:manager]
},
‘stores’ => {
‘show’ => [:clerk, :manager],
‘new’ => [:manager],
‘edit’ => [:manager]
}
}
roles = access_rules[controller_name][action_name]
return true if roles.any? { |role| current_user.send("#{role}?") }
return false
Something like that anyway. I even went so far as to write a controller
plugin so I could simplify it to
allow_access(:clerk, :only => [:show])
allow_access(:manager, :only => [:show, :new, :edit])
verify_access
This is obviously a contrived example, but it should suffice to get the
point across. Bringing this back to RSpec, specs make more sense this
way as you can check to make sure your role methods on the user model
return true or false based on a database setting and you can easily
mock/stub those methods in the controller specs to make sure that you
don’t get to actions that you shouldn’t.
By the way, I prefer English breakfast tea and Indian spiced chai.
Peace.
Phillip