# Before\_filter with multiple roles

**URL:** <https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265>\
**Category:** Rails\
**Created:** [May 21, 2008, 2:54pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265 "2008-05-21T14:54:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 2:54pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/1 "2008-05-21T14:54:29Z")

</div>

I have multiple roles in my application.  
Now I want to block a method for all users except the administrator and  
a manager.  
When I do this:

before\_filter (:check\_administrator\_role), :only =\> [:administration]  
before\_filter (:check\_taskmanager\_role), :only =\> [:administration]

The user must have both roles. How can I change that to an “OR”  
combination?

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 3:35pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/2 "2008-05-21T15:35:26Z")

</div>

On Wed, May 21, 2008 at 8:54 AM, Sjoerd Schunselaar  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> combination?  
> How about

before\_filter(:admin\_authorized), :only =\> [:administration]

def admin\_authorized  
check\_administrator\_role || check\_taskmanager\_role  
end

or

before\_filter :only =\> [:administration] {|controller, action|  
controller.check\_administrator\_role ||  
controller.check\_taskmanager\_role}

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 4:18pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/3 "2008-05-21T16:18:06Z")

</div>

On 21 May 2008, at 15:12, Sjoerd Schunselaar wrote:

> before\_filter (:check\_administrator\_role || :check\_taskmanager\_role),  
> :only =\> [:administration]  
> You can’t do anything like that. you need to produce a single filter  
> that performs the check (which seems to be what rick’s suggestion is).

Fred

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 4:12pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/4 "2008-05-21T16:12:38Z")

</div>

Thank you, but both method does not work.  
Maby I’m stupid (This is my first month with RoR), but in my application  
a user has only one role. So the first method does not work. And the  
second method I don’t understand. What do I have to fill in as  
controller, and action? Also he said “{” is unexpected at your second  
method.

I’ve also tried;  
before\_filter (:check\_administrator\_role || :check\_taskmanager\_role),  
:only =\> [:administration]

Rick Denatale wrote:

> On Wed, May 21, 2008 at 8:54 AM, Sjoerd Schunselaar  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > combination?  
> > How about
> 
> before\_filter(:admin\_authorized), :only =\> [:administration]
> 
> def admin\_authorized  
> check\_administrator\_role || check\_taskmanager\_role  
> end
> 
> or
> 
> before\_filter :only =\> [:administration] {|controller, action|  
> controller.check\_administrator\_role ||  
> controller.check\_taskmanager\_role}
> 
> –  
> Rick DeNatale
> 
> My blog on Ruby  
> [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 9:00pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/5 "2008-05-21T21:00:55Z")

</div>

I was about to suggest something along the lines of Rick’s last  
suggestion. Why note create a single method with a sponge parameter  
so that it accepts one or more role names and returns whether or not  
the user is one or more of those roles? If you did that then you  
could include the method in your ApplicationController and share the  
logic with all your controllers.

def authorized\_for\_roles(\*roles)  
roles.each{|role\_name| return true if user.has\_role?(role\_name)}  
false  
end

With that you could have a before\_filter like this:

before\_filter :authorize\_administration, :only=\>:administration  
…  
private  
def authorize\_administration  
authorized\_for\_roles :administrator, :taskmanager  
end

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 22, 2008, 8:44am UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/6 "2008-05-22T08:44:40Z")

</div>

After reading your and Ricks post I understand what my problem was. Now  
I use this in my authentication controller, and it seems al working  
fine.

def authorized\_for\_roles(\*roles)  
roles.each{|role| return true if @current\_user.has\_role?(role)}  
permission\_denied  
end

Thank you for the quick and good response!

AndyV wrote:

> I was about to suggest something along the lines of Rick’s last  
> suggestion. Why note create a single method with a sponge parameter  
> so that it accepts one or more role names and returns whether or not  
> the user is one or more of those roles? If you did that then you  
> could include the method in your ApplicationController and share the  
> logic with all your controllers.
> 
> def authorized\_for\_roles(\*roles)  
> roles.each{|role\_name| return true if user.has\_role?(role\_name)}  
> false  
> end
> 
> With that you could have a before\_filter like this:
> 
> before\_filter :authorize\_administration, :only=\>:administration  
> …  
> private  
> def authorize\_administration  
> authorized\_for\_roles :administrator, :taskmanager  
> end

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [July 16, 2008, 4:56am UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/7 "2008-07-16T04:56:48Z")

</div>

hi…

can u explain to me what is “@current\_user.has\_role?(role)” means.  
“has\_role” izzit a method that u define by urself ?

Thanks You!!!

On May 22, 2:44 pm, Sjoerd Schunselaar \<rails-mailing-l…@andreas-

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [July 16, 2008, 4:56am UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/8 "2008-07-16T04:56:49Z")

</div>

hi  
i am new to rails. i tried to create a site with multiple role as  
described above.  
when i tried the following code  
def authorized\_for\_roles(\*roles)  
roles.each{|role| return true if @current\_user.has\_role?(role)}  
permission\_denied  
end  
i got the following error  
You have a nil object when you didn’t expect it!  
The error occurred while evaluating nil.has\_role?

can anyone explain what is wrong.

thank you

On May 22, 2:44 pm, Sjoerd Schunselaar \<rails-mailing-l…@andreas-

---

<div class="post-metadata">

**Author:** ![sschunselaar](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/34f0e0/32.png) [@sschunselaar](https://www.ruby-forum.com/u/sschunselaar)\
**Post date:** [May 21, 2008, 6:21pm UTC](https://www.ruby-forum.com/t/before-filter-with-multiple-roles/138265/9 "2008-05-21T18:21:33Z")

</div>

On Wed, May 21, 2008 at 10:17 AM, Frederick C.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > controller, and action? Also he said “{” is unexpected at your second  
> > method.
> > 
> > I’ve also tried;  
> > before\_filter (:check\_administrator\_role || :check\_taskmanager\_role),  
> > :only =\> [:administration]  
> > You can’t do anything like that. you need to produce a single filter  
> > that performs the check (which seems to be what rick’s suggestion is).

Yes that’s what I was suggesting.

I think the problem was I didn’t really go into how filters work. the  
two existing check\_xxx\_role methods probably look something like:

def check\_administrator\_role  
redirect\_to somewhere unless user.has\_role(:administrator)  
end

def check\_taskmanager\_role  
redirect\_to somewhere unless user.has\_role(:taskmanager)  
end

So my simple admin\_authorized method will actually stop the filter  
chain unless the user has BOTH roles rather than either, instead  
rather than calling the other two filter methods, it need to do  
something like:

def admin\_authorized  
redirect\_to somewhere unless user.has\_role(:administrator) ||  
user.has\_role(:taskmanager)  
end

or some equivalent logic.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
