= SUMMARY
An ActionController +verify+ directive redirects to an :action if
certain actions are not done by POST. In one case, the redirect is to an
empty hash instead; in another, nearly identical, it is to the correct
hash. This is seen in a functional test.
Will someone please tell me what is going wrong, and how I can correct
it?
= ENVIRONMENT
$ ruby --version
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
$ rails --version
Rails 1.2.6
= DETAIL
(Much of this may be easier to see in the “CODE” section, below.)
AdminController is a subclass of ActionController, acting on instances
of Permission, an ActiveRecord subclass. Permission#approve and
Permission#deny set the :approval attribute to one string or another.
admin/approve/:id and admin/deny/:id pass the respective methods to the
id’ed Permission.
AdminController has a +verify+ directive to require that #approve and
#deny be done by POST. If they are not, the session is to :redirect_to
admin/list.
Class AdminControllerTest, a Test::Unit::TestCase, challenges the
+verify+ by using GET requests instead. For many iterations of the test,
AdminController passed. I then added some tests to AdminControllerTest;
I did not change test_deny_not_post or test_accept_not_post.
test_deny_not_post then started failing at assert_redirected_to. The
fail message is:
“response is not a redirection to all of the options supplied
(redirection is <{}>), difference: <{“action”=>:list}>”
test_approve_not_post, which is nearly identical, DOES NOT fail.
Changing the +verify+'s :redirect_to to { :controller => :admin, :action
=> :list } gets the tests past the assert_redirected_to, but fails the
follow_redirect (Can’t follow redirects outside of current controller
(from admin to admin)). This failure is in BOTH test_deny_not_post and
test_approve_not_post.
My controller is failing a functional test, and I don’t understand why.
Will someone please tell me what is going wrong, and how I can correct
it?
= CODE (abridged)
class AdminController < ApplicationController
verify :method => :post, :only => [ :destroy, :create, :update,
:deny, :approve ],
:redirect_to => { :action => :list },
:add_flash => { :notice => ‘You cannot do this directly.’ }
def approve
# before_filter sets @permission
@permission.approve
if @permission.save
flash[:notice] = ‘This request was approved.’
else
flash[:notice] = ‘Could not approve the request (internal
error).’
end
redirect_to :action => :list
end
def deny
# before_filter sets @permission
@permission.deny
if @permission.save
flash[:notice] = ‘This request was denied.’
else
flash[:notice] = ‘Could not deny the request (internal error).’
end
redirect_to :action => :list
end
class AdminControllerTest < Test::Unit::TestCase
#setup puts user credentials in @session
def test_approve_not_post
get :approve, { :id => 3 }, @session
assert_response :redirect
assert_redirected_to :action => :list
assert_equal ‘You cannot do this directly.’, flash[:notice]
end
def test_deny_not_post
get :deny, { :id => 3 }, @session
assert_response :redirect
assert_redirected_to :action => :list
assert_equal ‘You cannot do this directly.’, flash[:notice]
end
end