Следующий attempt_login
метод вызывается с использованием Ajax после отправки формы входа.
class AccessController < ApplicationController
[...]
def attempt_login
authorized_user = User.authenticate(params[:username], params[:password])
if authorized_user
session[:user_id] = authorized_user.id
session[:username] = authorized_user.username
flash[:notice] = "Hello #{authorized_user.name}."
redirect_to(:controller => 'jobs', :action => 'index')
else
[...]
end
end
end
Проблема в том, что redirect_to
это не работает.
Как бы вы это решили?
ruby-on-rails
ajax
ruby-on-rails-3
redirect
Миша Морошко
источник
источник
render :js => "window.location = '#{jobs_path}'"
jobs_path
такой уж жесткий, как URL? Если URL-адрес изменится, изменится и имя маршрута, если только вы не проявите особую осторожность. Другой альтернативой было быrender js: "window.location = '#{polymorphic_path(@job.class)}'"
использование рассчитанного ресурсного маршрута на основе модели Job. Это работает, только если ваши маршруты изобретательны и используют стандартные соглашения об именах, которые соответствуют вашим моделям. (Или если вы укажете model_name на своих моделях, чтобы они генерировали правильные имена маршрутов.)Есть очень простой способ сохранить вспышку для следующего запроса. В вашем контроллере сделайте что-то вроде
flash[:notice] = 'Your work was awesome! A unicorn is born!' flash.keep(:notice) render js: "window.location = '#{root_path}'"
flash.keep
Будет убедиться , что вспышка сохраняется для следующего запроса. Поэтому приroot_path
рендеринге будет отображаться данное флэш-сообщение. Rails - это круто :)источник
Думаю, это немного приятнее:
render js: "window.location.pathname='#{jobs_path}'"
источник
render js: "window.location.pathname = #{jobs_path.to_json}"
В одном из своих приложений я использую JSON для перенаправления и передачи данных флэш-сообщений. Это выглядело бы примерно так:
class AccessController < ApplicationController ... def attempt_login ... if authorized_user if request.xhr? render :json => { :location => url_for(:controller => 'jobs', :action => 'index'), :flash => {:notice => "Hello #{authorized_user.name}."} } else redirect_to(:controller => 'jobs', :action => 'index') end else # Render login screen with 422 error code render :login, :status => :unprocessable_entity end end end
И простой пример jQuery:
$.ajax({ ... type: 'json', success: functon(data) { data = $.parseJSON(data); if (data.location) { window.location.href = data.location; } if (data.flash && data.flash.notice) { // Maybe display flash message, etc. } }, error: function() { // If login fails, sending 422 error code sends you here. } })
источник
Сочетание лучшего из ответов:
... if request.xhr? flash[:notice] = "Hello #{authorized_user.name}." flash.keep(:notice) # Keep flash notice around for the redirect. render :js => "window.location = #{jobs_path.to_json}" else ...
источник
def redirect_to(options = {}, response_status = {}) super(options, response_status) if request.xhr? # empty to prevent render duplication exception self.status = nil self.response_body = nil path = location self.location = nil render :js => "window.location = #{path.to_json}" end end
источник
Я не хотел изменять действия своего контроллера, поэтому я придумал этот хак:
class ApplicationController < ActionController::Base def redirect_to options = {}, response_status = {} super if request.xhr? self.status = 200 self.response_body = "<html><body><script>window.location.replace('#{location}')</script></body></html>" end end end
источник