Redirecting to another controller, with a POST method


#1

Hi.

How do I call a method in controller B from controller A and ensure it
is treated as a POST method? I have a method in my account_controller:

#CONTROLLER: ACCOUNT
def logout
if request.post?
#isn’t reached when redirected to from users_controller:
reset_session
flash[:notice] = “You have been logged out.”
end
#execution continues here:
redirect_to index_url
end

When I call it from users_controller like this:

#CONTROLLER: USERS
if @user == logged_in_user
if @user.destroy
flash[:notice] = “Your account has been deleted”
redirect_to :controller => ‘account’, :action => ‘logout’
else
flash[:error] = “There was a problem deleting your account.”
end

it doesn’t execute the part conditioned by the if request.post?
statement. In a view / .rhtml file, I call this same method like this:

<%= link_to ‘Logout’, {:controller => ‘account’, :action => ‘logout’},
:method => :post %>

and it works no problem. I have tried:

redirect_to :controller => ‘account’, :action => ‘logout’, :method =>
:post

in the users_controller but it still doesn’t positively evaluate the if
request.post? part.

Thanks a lot!

/ Vahagn


#2

first of all: i don’t know if using POST with a redirect is possible.

but other than that: i don’t think you really need that.

on the one hand you could just leave that
if request.post?
out and everything is fine. i don’t think you really need to check for
POST in logout. the user is not submitting any data.

on the other hand (if you want to stick to that POST thing) you could
add something like this:
if request.post? or params[:redirect]

now in your redirection just add
, :params => {:redirect => true}

that should do the trick


#3

Cheers MaD,-

thanks for the reply. Here’s what I’ll do:

if @user == logged_in_user
if @user.destroy
flash[:notice] = “Your account has been deleted”
reset_session #the meat of the logout method
else
flash[:error] = “There was a problem deleting your account.”
end

That may seem like duplication, but I don’t want to break my logout
method with the if request.post? conditional (although I don’t
understand what is being POST’ed there, as you write. This is code from
a tutorial and is by far working fine.)

I’d really like to know:

  1. why is it necessary to check for “if request.post?” in the logout
    method;
  2. why one can redirect to that method from a view, like this:

<%= link_to ‘Logout’, {:controller => ‘account’, :action => ‘logout’},
:method => :post %>

but cannot do the same from a controller.

Anyone?

/V.


#4

i think the difference is that form a view there can be a real POST
(with user submitting data, pressing a button, …), but a controller
just GETs infos and stuff. i’m no expert, so that is just a guess.

normally you POST things that create or destroy things. in other words
actions that make a difference. “logout” is somewhere in between. it
doesn’t really do anything harmful or constructive, but it changes the
state of your user. so in my opinion, logout could as well be a POST
as a GET method. in my last project i didn’t check for POST in my
logout-action. btw: authlogic doesn’t do that either in their example.


#5

Hi,

You cannot redirect with a POST method, so you’ll have to find a trick
to circumvent that issue.


#6

Hi MaD,-

yep, I can see your line of reasoning. It appears that it is probably
not very RESTful to check for POST, so that can be dropped altogether.
It seems conceptually wrong that you need to ensure something is
POST’ed, but then it only works from a view and not a controller. If
something is POST’ed, I think it should be uniform throughout the
application / MVC stack. Convention over configuration / principle of
least surprise. Just my 5 cents.

Cheers, Vahagn


#7

Fernando P. wrote:

Hi,

You cannot redirect with a POST method, so you’ll have to find a trick
to circumvent that issue.

Right!

Cheers, Vahagn