# Best way to verify request method

**URL:** <https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529>\
**Category:** Rails\
**Created:** [April 22, 2008, 10:09pm UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529 "2008-04-22T22:09:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [April 22, 2008, 10:09pm UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529/1 "2008-04-22T22:09:25Z")

</div>

I did some googling, but didn’t find anything that specifically  
addressed my question, but if you have a link, I’d really appreciate it.

I want to build some robustness into my controllers by blocking access  
to actions via the wrong request method. For example, I don’t want to  
allow a POST to the :index action. I started using the verify method,  
such as

verify :method =\> :get, :only =\> [:index, :new, :edit], :redirect\_to =\>  
whatever

This worked well until I added some before\_filters. It appears to me  
that before\_filters are processed before verify, and that is opposite  
what I am trying to achieve. I’d like to check the request method before  
anything else happens.

I came up with an approach in which I use a real before filter and a  
hash of controllers, methods, and acceptable actions. It looks like

class ApplicationController \< ActionController::Base

before\_filter :verify\_request\_method

protected

def verify\_request\_method  
if !request\_method\_valid?(controller\_name.to\_sym,  
action\_name.to\_sym, request.method.to\_sym)  
flash[:error] = ‘Invalid request method.’  
redirect\_to error\_path and return false  
end

```
return true

```

end

private

def request\_method\_valid?(controller, action, method)  
valid\_request\_methods = {  
:welcome =\> {  
:get =\> [:index, :about],  
:post =\> [],  
:put =\> [],  
:delete =\> []  
},  
:users =\> {  
:get =\> [:show, :new, :edit],  
:post =\> [:create],  
:put =\> [:update],  
:delete =\> []  
},  
:sessions =\> {  
:get =\> [],  
:post =\> [:new],  
:put =\> [],  
:delete =\> [:destroy]  
}  
}

```
return valid_request_methods[controller][method].include?(action)

```

end  
end

This works, but I’m curious if I’m making it more difficult than it  
needs to be. Is there an easier way?

Peace,  
Phillip

---

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [April 22, 2008, 11:50pm UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529/2 "2008-04-22T23:50:02Z")

</div>

I think you are a bit confused. You mention “It appears to me  
that before\_filters are processed before verify, and that is opposite  
what I am trying to achieve. I’d like to check the request method before  
anything else happens.”

But there is nothing magic about verify. Check out the source for  
verify:

[http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html](http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html)

ie:

def verify(options={})  
filter\_opts = { :only =\> options[:only], :except =\> options[:except] }  
before\_filter(filter\_opts) do |c|  
c.send! :verify\_action, options  
end  
end

verify IS a before filter. You just have to make sure you order it  
properly so that it is the first filter to run. You really should stick  
with verify since it is already a before filter you sort of just  
reimplemented verify…

---

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [April 23, 2008, 1:03am UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529/3 "2008-04-23T01:03:38Z")

</div>

Nathan E. wrote:

> I think you are a bit confused. You mention “It appears to me  
> that before\_filters are processed before verify, and that is opposite  
> what I am trying to achieve. I’d like to check the request method before  
> anything else happens.”
> 
> But there is nothing magic about verify. Check out the source for  
> verify:
> 
> [http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html](http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html)
> 
> ie:
> 
> def verify(options={})  
> filter\_opts = { :only =\> options[:only], :except =\> options[:except] }  
> before\_filter(filter\_opts) do |c|  
> c.send! :verify\_action, options  
> end  
> end
> 
> verify IS a before filter. You just have to make sure you order it  
> properly so that it is the first filter to run. You really should stick  
> with verify since it is already a before filter you sort of just  
> reimplemented verify…

Thanks, Nathan. I knew that verify is _essentially_ a before\_filter,  
but I guess I never thought about it _being_ a before filter. Now that  
I think of it, I may have positioned it after the before\_filters in my  
controller. Not sure why. And that, of course, would have produced the  
before\_filter first, verify last pattern that caused me problems.

As to your comment about me reinventing verify, that’s exactly what I  
did because I didn’t know what else to do. I’d much stay with what’s  
already built in, so I will reposition verify to the head of my  
controllers and re-test. The advantage to my approach, though, is that  
it’s all in one place, and if I want/need to change the action to take,  
I only have to do it in one place. I don’t, however, have all of the  
other capabilities that verify has.

Thanks for clearing up some of my confusion.

Peace,  
Phillip

---

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [April 23, 2008, 2:29am UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529/4 "2008-04-23T02:29:59Z")

</div>

Are named routes not recognized in before\_filters? I changed my  
controller to

class UsersController \< ApplicationController  
verify :method =\> :get, :only =\> [:show, :new, :edit], :add\_flash =\>  
{:error =\> ‘Invalid request method’}, :redirect\_to =\> error\_path  
verify :method =\> :post, :only =\> [:create], :add\_flash =\> {:error =\>  
‘Invalid request method’}, :redirect\_to =\> error\_path  
verify :method =\> :put, :only =\> [:update], :add\_flash =\> {:error =\>  
‘Invalid request method’}, :redirect\_to =\> error\_path

and get an error that ‘error\_path’ is an undefined local variable, yet  
it works in other places as one would expect. I also tried using a  
helper to return error\_path (which is already a helper!), and that  
didn’t work either.

I’m also thinking that my method, though not “proper” Rails, is more DRY  
and easier to use. In my case, I put the filter in  
ApplicationController so all controllers can use it automatically. I  
need to add one hash per controller for the actions I want to protect,  
and that’s it. I need to put an exclude test in there for any  
controller that I don’t want to use this on, but that’s easy. Using  
verify straight away, I need to add the calls for each request method in  
each controller, and if I change the behavior of failed verifications, I  
have to modify all controllers.

I think I’ll keep using my approach as long as it serves its purpose and  
doesn’t present any obstacles. If it does, I’ll step back and  
re-evaluate.

Thanks again for your input Nathan. I really appreciate people taking  
the time to share their knowledge.

Peace,  
Phillip

---

<div class="post-metadata">

**Author:** ![pkoebbe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ec9cab/32.png) [@pkoebbe](https://www.ruby-forum.com/u/pkoebbe)\
**Post date:** [April 23, 2008, 2:37am UTC](https://www.ruby-forum.com/t/best-way-to-verify-request-method/135529/5 "2008-04-23T02:37:58Z")

</div>

The verify method would work like this:

verify :method =\> :get, :only =\> [:show, :new, :edit], :add\_flash =\>  
{:error =\> ‘Invalid request method’}, :redirect\_to =\> :error\_path  
verify :method =\> :post, :only =\> [:create], :add\_flash =\> {:error =\>  
‘Invalid request method’}, :redirect\_to =\> :error\_path  
verify :method =\> :put, :only =\> [:update], :add\_flash =\> {:error =\>  
‘Invalid request method’}, :redirect\_to =\> :error\_path

Note that the urls are symbols in the filter because this is happening  
at the class level where they are not defined. The symbols are later  
turned into the appropriate url.
