Kilka redirect_to w jednej akcji

Witam.
Czemu nie można umieścić kilku przekierowań w jednej akcji? Chcę wykonać coś takiego:

[code=app/controllers/sessions_controller.rb]def create
@user = User.authenticate(params[:session][:email], params[:session][:password])
respond_to do |format|
format.html {
if @user.nil?
flash[:error] = t(‘attributes.session.error’)
@title = t(‘app.titles.new_session’)
render ‘new’
else
sign_in @user
redirect_to(@user) and return
end
}
format.js {
if @user.nil?
render :partial => ‘login_failed’
else
render :partial => ‘login_successful’
redirect_to(@user)
end
}
end

end[/code]
Przy poprawnym zalogowaniu Mongrel rzuca błędami:

AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".):
Nie da się standardowo przekierować użytkownika do jego strony (/users/:id) jeśli formularz ma ustawione :remote => true i JS jest w przeglądarce włączony?

Bo specyfikacja HTTP oraz implementacje pozwalają na tylko jeden redirect w odpowiedzi. Możesz mieć wiele redirectów w jednej akcji ale wykonać się może tylko jeden z nich (czyli jakiś if albo case w użyciu musi być).

W Twoim przypadku jest zarówno render jak i redirect:

render :partial => 'login_successful'
redirect_to(@user)

Albo jedno albo drugie :).

Oczywiście, mój błąd. Źle sformułowałem pytanie.

Mój problem chyba rysuje się nieco inaczej. Zdaje się, że problem leży w tej części kodu:

render :partial => 'login_successful' redirect_to(@user)
Ale tu pojawia się kolejny. W _login_failed i _login_successful mam kod JS ospowiedzialny za wyświetlenie alertów z odpowiednią informacją. Chcę zatem żeby alert przy poprawnym zalogowaniu się wyświetlał i następnie/równolegle następowało przekierowanie do strony użytkownika. Gdy wpiszę do ‘create.js.erb’:

<% unless @user.nil? %> $(function(){ alert('Zalogowano'); return false; }); <% else %> $(function(){ alert("Logowanie nieudane"); return false; }); <% end %>
i usunę partiale przy błędzie logowania alert się wyświetla, natomiast przy udanym logowaniu nie ma już błędu DoubleRender, nie ma też alertu jednak w logach pojawia się taki babol:

[code]Started POST “/sessions” for 127.0.0.1 at 2010-08-24 16:33:38 +0200
Processing by SessionsController#create as JS
Parameters: {"_snowman"=>“:snowman_with_snow:”, “authenticity_token”=>“R3YZAuu/BlBP+K2h0hZI4bRsOBn0a4iXfIRqjSJoaVM=”, “session”=>{“email”=>"bfo@example.com", “password”=>"[FILTERED]"}}
User Load (4.7ms) SELECT “users”.* FROM “users” WHERE (“users”.“email” = ‘bfo@example’) LIMIT 1
Redirected to http://localhost:3000/users/5
Completed 302 Found in 187ms
s

Started GET “/users/5” for 127.0.0.1 at 2010-08-24 16:33:38 +0200
Processing by UsersController#show as HTML
Parameters: {“id”=>“5”}
User Load (6.3ms) SELECT “users”.* FROM “users” WHERE (“users”.“id” = 5) LIMIT 1
Rendered sessions/_login_form.html.erb (5.2ms)
Rendered users/show.html.erb within layouts/application (23.1ms)
Completed 200 OK in 192ms (Views: 29.2ms | ActiveRecord: 6.3ms)[/code]
Jednakże nie powoduje to wyrenderowania show.html.erb w żadanym miejscu.

Wywal redirect z tego miejsca w kontrolerze o którym wspominasz i użyj window.location z timeoutem w kodzie JavaScript aby zrobić redirect z opóźnieniem.

O żesz. Jakieś zaćmienie mnie ogarnęło. A tyle czasu się zastanawiałem jak można przekierować w JS… i doszedłem do wniosku, że się nie da :stuck_out_tongue: