assert_pedantic_semantic_thing
mly : June 17th, 2006
Say you're getting into the whole RESTful thing and realizing that maybe it isn't such a good idea to allow GET requests to modify something. Being the good citizen you are, you set about requiring all your state-modifying actions to require POST requests. Looking at the examples you might do something like this (taken from a [DHH comment](http://www.loudthinking.com/arc/000529.html)):
verify :method => :post, :only => :delete,
:redirect_to => { :action => "forbidden_verb" }
Which looks all nice and neat except for the fact that it's stupidly un-semantic and wasteful to boot. After all, isn't this what the [405 response code](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6) is for?
Keeping with the spirit of letting HTTP do its job, we instead create a verify statement like so:
verify :only => [:update], :method => :post, :render => {:status => 405, :text => 'Method Not Allowed'}, :add_headers => {'Allow' => 'POST'}
where `:only` points to the methods we want to protect by being POST only.
This is fine and dandy, but you want to make certain that these methods work, and that future updates to rails don't break things, so you're a good developer who eats his Wheaties and writes his tests. However, you also like DRY and want to keep it simple. So I'll cut out the work for you and just tell you to stick this in your `test_helper.rb`:
def assert_header(header, expected)
if expected.is_a?(String)
assert_equal @response.headers[header], expected
elsif expected.is_a?(Regex)
assert @response.headers[header].match(expected), "#{@response.headers[header]} does not match #{expected}"
else
assert false, expected + " is not a String or Regex"
end
end
def assert_method_not_allowed(action, params={})
parameters, good, methods = params[:params] || {}, params[:good] || :post, params[:bad] || :get
methods = [methods].flatten
methods.each do |m|
send m, action, parameters
assert_header('Allow', good.to_s.upcase)
end
end
You can then do this sort of thing in your functional tests:
def test_update__with_get
assert_method_not_allowed(:update, {:good => :post, :bad => :get})
end
Note that you could leave off the hash that is the second argument, since those are default values.
Customize to taste by checking out the first line of the `assert_method_not_allowed` definition.
5 Responses to “assert_pedantic_semantic_thing”
Sorry, comments are closed for this article.
June 19th, 2006 at 08:01 AM Very nice tutorial, thanks!
June 27th, 2006 at 08:26 PM I feel I should mention that the new simply_restful stuff (the plugin, that will be in 1.2) pretty much makes this all obsolete, and rightfully so. If you're not comfortable living on the edge, however, this can still be useful.
July 5th, 2006 at 10:57 AM Why not DRY out that verify line a little too:
July 10th, 2006 at 06:15 AM To those that come back later: :add_headers is only available in Edge Rails. lukfugl: An optional array argument must follow any regular arguments. So *methods must be switched with options. Which unfortunately hurts semantics.
June 18th, 2007 at 02:21 PM
Hello! Good Site! Thanks you! jeylmuheko