Ответ 1
Хорошо, я, наконец, понял это. Я не уверен, что это вообще изменилось с обновлением, которое Devise сделал вчера, когда Devise:: Mailer поместил большую часть своих функций в модуль (см. Код здесь и билет здесь).
В основном это сводится к невозможности доступа к session
внутри представления почтовой программы. Поэтому вам нужно передать перенаправление в качестве переменной. Devise использует метод after_create
на вашем ресурсе (User
в моем случае), который затем отправляет письмо с подтверждением. Это означало, что я не мог просто передать переменную сеанса непосредственно почтовой программе. Таким образом, я чувствую, что это довольно неприятная работа, чтобы получить эту функциональность. Но вот код.
Итак, чтобы получить переменную redirect_to в почтовой программе, вам нужно добавить переменную пользователю. Таким образом:
class User < ActiveRecord::Base
…
attr_accessor :return_to
…
end
Затем вы должны установить эту переменную при создании пользователя в первый раз. У меня уже была настраиваемая настройка контроллера для регистрации (см. Создание Readme о том, как это установить, или см. Ответ @ramc для направления). Но было довольно легко сделать эту часть, я просто добавил ее к параметрам, и пусть остальные позаботятся о себе.
class RegistrationsController < Devise::RegistrationsController
def create
params[:user][:return_to] = session[:user_return_to] if session[:user_return_to]
…
super
end
end
Теперь пользователь имеет переменную return_to
, которая установлена. Нам просто нужно получить доступ к этому в электронном письме confirm_instructions. Я уже переписал часть confirm_instructions.html.erb, поэтому внутри там я добавил:
<% if @resource.return_to %>
<%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token, :redirect_to => @resource.return_to) %>
<% else %>
<%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>
<% end %>
(для тех, кто не знаком с этим, @resource - это переменная, которую Devise использует для определения вашего пользователя).
Теперь, когда пользователь нажимает на эту ссылку, мы должны перенаправить их. @ramc до того, как фильтр хорошо работает для этого.
class ConfirmationsController < Devise::ConfirmationsController
before_filter :set_redirect_location, :only => :show
def set_redirect_location
session[:user_return_to] = params[:redirect_to] if params[:redirect_to]
end
end
Это позаботится о случае, когда новый пользователь переходит на защищенную страницу, затем подписывается, нажимает на ссылку подтверждения и перенаправляется на защищенную страницу.
Теперь нам просто нужно позаботиться о случае, когда пользователь делает это, но вместо того, чтобы нажимать на ссылку, они пытаются вернуться на защищенную страницу. В этом случае их просят зарегистрироваться/войти в систему. Они регистрируются, а затем просят подтвердить их электронную почту и им предоставляется возможность повторно отправить письмо с подтверждением. Они добавили свой адрес электронной почты, и теперь мы должны поместить переменную redirect_to в это новое электронное письмо с подтверждением.
Для этого нам нужно изменить ConfirmationController, аналогично тому, как мы сделали RegistrationController. На этот раз нам нужно изменить метод создания. Способ, которым это работает, состоит в вызове метода класса для пользователя с именем send_confirmation_instructions
. Мы хотим переписать этот метод, чтобы мы могли передать в него переменную return_to
.
class ConfirmationsController < Devise::ConfirmationsController
def create
self.resource = resource_class.send_confirmation_instructions(params[resource_name],session[:user_return_to])
if resource.errors.empty?
set_flash_message(:notice, :send_instructions) if is_navigational_format?
respond_with resource, :location => after_resending_confirmation_instructions_path_for(resource_name)
else
respond_with_navigational(resource){ render_with_scope :new }
end
end
end
Единственное, что отличается от того, что приходит с разработкой, это первая строка создания. Мы передаем две переменные в. Теперь нам нужно переписать этот метод.
class User < ActiveRecord::Base
def self.send_confirmation_instructions(attributes={},redirect=nil)
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
confirmable.return_to = redirect if confirmable.persisted?
confirmable.resend_confirmation_token if confirmable.persisted?
confirmable
end
end
confirmable
становится экземпляром пользователя (текущий пользователь на основе электронной почты). Поэтому нам просто нужно установить return_to
.
Что это.