user_signed_in rails gema create ruby-on-rails-3 devise

ruby on rails 3 - rails - Devise-Redirigir la página después de la confirmación



install devise rails 5 (3)

Digamos que un usuario hace clic en un enlace a una página que está protegida. Luego se redirigen a una pantalla de inicio de sesión donde pueden iniciar sesión. Si lo hacen, se redirigen con éxito a esa página. Pero si no tienen una cuenta tienen que registrarse. Aquí es donde las cosas se complican porque estoy haciendo una confirmación por correo electrónico.

Al hacer clic en un enlace, se crea una nueva sesión si no puedo redirigir automáticamente al usuario a esa página protegida. Estoy intentando cambiar esto poniendo una referencia a la redirección dentro del enlace de confirmación. Me gustaría hacer:

<%= link_to ''Confirm my account'', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token, :redirect_to => stored_location_for(@resource)) %>

Pero no puedo averiguar cómo obtener acceso a stored_location_for (o si esa es incluso la ubicación correcta para obtener). Se define en Devise::Controllers::Helpers , pero es un método de instancia, por lo que no puedo hacer Devise::Controllers::Helpers.stored_location_for(…) .

Mi pregunta es ¿cómo obtengo acceso a stored_location_for O O cuál es la mejor manera de hacer esto?

Mi objetivo es hacer eso y luego en mi ConfirmationsController personalizado definir:

def show if params[:redirect_to] session["user_return_to"] = params[:redirect_to] end super end

Eso debería funcionar bien?


En cuanto a la forma de storage_location_for se ha implementado en lib / devise / controllers / helpers.rb

def stored_location_for(resource_or_scope) scope = Devise::Mapping.find_scope!(resource_or_scope) session.delete("#{scope}_return_to") end

De lo contrario, es posible acceder a él mediante la sesión [''user_return_to'']. En su caso, perdería ese objeto de sesión porque cuando el usuario hace clic en el enlace del correo de confirmación, puede ser una sesión nueva que se genera.

Puede implementar lo que haya sugerido como un filtro anterior:

class Users::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

Además de esto, tendrá que modificar la ruta para hacer que el dispositivo llame a su controlador en lugar de su propio controlador de confirmación.

devise_for :users, :controllers => { :confirmations => ''users/confirmations''}

Espero que esto ayude :)

Nota: los fragmentos de código no están completos y solo contienen detalles relevantes.


Ok, finalmente lo descubrí. No estoy seguro de si esto cambia en absoluto con la actualización que hizo Devise ayer al hacer que Devise :: Mailer pusiera la mayor parte de su funcionalidad en un módulo (vea el código here y el ticket here ).

Básicamente, se reduce a no poder acceder a la session dentro de una vista de correo. Por lo tanto tienes que pasar la redirección como variable. Devise utiliza un método after_create en su recurso ( User en mi caso) que luego envía el correo electrónico de confirmación. Esto significaba que no podía pasar la variable de sesión directamente al remitente. Por lo tanto, siento que este es un trabajo bastante desagradable para obtener esta funcionalidad. Pero aquí está el código.

Entonces, para obtener la variable redirect_to en la aplicación de correo, debe agregar una variable al usuario. Así:

class User < ActiveRecord::Base … attr_accessor :return_to … end

Luego tienes que establecer esa variable cuando creas al usuario por primera vez. Ya tenía una configuración de controlador personalizada para el registro (vea el tema sobre cómo configurar esto, o vea la respuesta de @ ramc para obtener instrucciones). Pero fue relativamente fácil hacer esta parte, simplemente la agregué a los parámetros y dejé que el resto se encargara de sí mismo.

class RegistrationsController < Devise::RegistrationsController def create params[:user][:return_to] = session[:user_return_to] if session[:user_return_to] … super end end

Ahora el usuario tiene una variable return_to que se establece. Solo necesitamos acceder a eso en el correo electrónico confirmación_instrucciones. Ya he reescrito parte de confirmation_instructions.html.erb, por lo que en ese momento acabo de agregar:

<% 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 %>

(para aquellos que son nuevos en esto, @resource es la variable que Devise usa para definir a su usuario).

Ahora, una vez que el usuario haga clic en ese enlace, debemos redirigirlos. El filtro de @ ramc''s funciona bien para esto.

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

Eso se hará cargo del caso en el que un nuevo usuario vaya a una página protegida, luego se registre, haga clic en el enlace de confirmación y se redireccione correctamente a la página protegida.

Ahora solo tenemos que ocuparnos del caso en el que un usuario hace lo anterior, pero en lugar de hacer clic en el enlace, intentan volver a la página protegida. En este caso, se les solicita que se registren / inicien sesión. Se registran y luego se les pide que confirmen su correo electrónico y se les da la opción de reenviar el correo electrónico de confirmación. Pusieron su correo electrónico y ahora necesitamos poner la variable redirect_to en ese nuevo correo electrónico de confirmación.

Para hacer esto necesitamos modificar el ConfirmationController, de manera similar a como lo hicimos con el RegistrationController. Esta vez necesitamos modificar el método de creación. La forma de trabajar fuera de la caja es llamar a un método de clase en el usuario llamado send_confirmation_instructions . Queremos reescribir ese método para que podamos pasarle la variable 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

Lo único diferente a lo que viene con el dispositivo es la primera línea de creación. Pasamos dos variables. Ahora necesitamos reescribir ese método.

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 convierte en una instancia de usuario (el usuario actual se basa en el correo electrónico). Así que solo necesitamos establecer return_to .

Eso es.


Por lo que puedo ver en los comentarios en el código fuente del dispositivo, todo lo que necesita hacer es implementar lo siguiente en su registrations_controller.rb:

def after_inactive_sign_up_path_for(resource_or_scope) session["user_return_to"] end