Здесь нужно преодолеть несколько проблем.
Браузеры в целом не позволяют перенаправлять запросы POST.
redirect_to не сохраняет формат без дополнительного ввода.
Местоположение магазина не сохраняет данные формы.
Все эти проблемы можно решить путем устранения перенаправлений.
Вот как я передал это в прошлом:
Вместо перенаправления в required_user, рендер. Если фильтр before перенаправляет или рендерит, ожидающее действие отменяется. (Нет необходимости возвращать false). К сожалению, этот маршрут стирает границы контроллера. Но допускает простой html-запасной вариант и делает его сухим.
Высокоуровневое представление нового рабочего процесса будет:
- Запрос аннотации # голосование (POST)
- Сбой фильтра обязательного пользователя
- рендеринг новой сессии
- отправить информацию для входа и исходные данные POST обратно в аннотации # голосование (POST)
- новый фильтр при голосовании собирает информацию о сеансе и регистрируется. Голосование проходит, как и ожидалось. Если войти не удается, вернитесь к 3.
- аннотации # голос перенаправляет / отображает, как следует
Начните с доработки require_user для рендеринга user_sessions # new template.
def require_user
unless current_user
flash[:notice] = "You'll need to login or register to do that"
@user_session ||= UserSession.new
respond_to do |format|
format.html {render :template => 'user_sessions/new'}
format.js {
render :template => 'user_sessions/new', :layout => false
}
end
end
end
@user_session ||= UserSession.new
гарантирует, что мы можем вернуть ошибки проверки в форму.
Теперь мы должны улучшить ваш новый шаблон user_session #, чтобы он мог запомнить действие. Также, если вы планируете использовать лайтбоксы, это должен быть частичный рендеринг, выполненный соответствующим RJS или new.html.erb.
Сначала мы создаем частичное для создания скрытых полей, сохраняющих данные POST, которые были бы потеряны при перенаправлении:
<% if params[:controller] == "annotations" %>
<% content_for :old_form do %>
<%= hidden_field_tag "annotation[song_id]", params[:annotation][:song_id] %>
<%= hidden_field_tag "annotation[vote]", params[:annotation][:vote] %>
<% end %>
<% end %>
Затем визуализируйте это частичное в частичном логине, которое займет ваш лайтбокс:
<%= render :partial => vote_form_replica %>
<% url = params[:controller] == "user_sessions ? user_sessions_url : {} %>
<% form_tag @user_session, :url => url do |f| %>
<%= yield :old_form %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= submit_tag %>
<%end%>
Пустой хеш для url в form_tag выглядит как ошибка, но это не так. Это гарантирует, что данные формы будут отправлены на URL, который отобразил форму. Которые на данный момент должны быть аннотациями /: id / voice
Теперь для нового фильтра войдите. По сути, он будет делать то, что когда-либо UserSessionsController # create делает без рендеринга / перенаправления. Следующее скопировано из плагина аутентификации RESTful.
def authenticate
self.current_user = User.authenticate(params[:login], params[:password])
if logged_in?
if params[:remember_me] == "1"
current_user.remember_me unless current_user.remember_token?
cookies[:auth_token] = { :value => self.current_user.remember_token,
:expires => self.current_user.remember_token_expires_at }
end
end
end
Осталось только убедиться, что порядок фильтров правильный.
before_filter :authenticate, :require_user, :only => :vote
N.B.: Вероятно, вы не собираетесь использовать эту версию require_user без этой версии authenticate, поэтому имеет смысл объединить их в один фильтр.
И это все. То, как это было настроено, позволяет создать надежный, СУХОЙ, легко повторно используемый код. Помещая новые фильтры в ApplicationController, они доступны в любом контроллере. С этого момента добавление этой функциональности к любым другим контроллерам / действиям занимает всего 3 простых шага:
- Создать новый частичный объект, смоделированный после частичного элемента voice_form_replica.
- Добавить соответствующий оператор рендеринга в новый шаблон сеанса.
- Примените фильтры к своим действиям.