Rails 6, permite al usuario ir a página esperada después de la autenticación

Cuando un usuario firma en Devise tomada a un nuevo_car_path por el método after_sign_in_path_for(). Sin embargo, hay situaciones en las que el Usuario tratará de ir a una página específica que necesita ser autenticada.

Mi ejemplo, el usuario registrado va directamente a "domain.com/cumplimiento-forma", esta página requiere que el usuario sea autenticado antes de alcanzarlo, así como se espera, se redirige a un signo en forma. Cuando el usuario se registra, los lleva al camino "after_sign_in_path_for", que en este cuidado es el "new_car_path".

Sin embargo, como el usuario sabe exactamente la página a la que quiere ir, quiero que vayan a "cumplir_form_path" "domain.com/cumplimiento-forma".

¿Cómo logro esto?

  def after_sign_in_path_for(_resource=nil)
    new_car_path
  end

Si agrego stored_location_for(resource) como usuario11350468 recomendado:

def after_sign_in_path_for(resource = nil)
  stored_location_for(resource) || new_car_path
end

Tengo el siguiente error,

NoMethodError en SessionsController #crear método indefinido `user_url' para #SessionsController:0x00007fc9f9bd1148 ¿Te refieres? search_url

THen agregó:

class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?
  
  def storable_location?
    request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
  end

  def store_user_location!
    store_location_for(:user, request.fullpath)
  end
end

Incluso después de agregar antes de la acción en el controlador, tengo el mismo error, aquí están los registros..

Started GET "/compliance_form for 127.0.0.1 at 2020-12-17 11:26:14 -0600
Processing by ComplianceController#new as HTML
Completed 401 Unauthorized in 4ms (ActiveRecord: 0.0ms | Allocations: 411)

Started GET "/users/sign_in" for 127.0.0.1 at 2020-12-17 11:26:14 -0600
Processing by SessionsController#new as HTML
  Rendering devise/sessions/new.html.erb within layouts/devise
  Rendered devise/sessions/new.html.erb within layouts/devise (Duration: 20.3ms | Allocations: 9174)
  Rendered layouts/_head.html.erb (Duration: 361.5ms | Allocations: 235189)
  Rendered layouts/_devise_navbar.html.erb (Duration: 3.7ms | Allocations: 901)
  Rendered layouts/_footer.html.erb (Duration: 0.1ms | Allocations: 5)
Completed 200 OK in 399ms (Views: 395.8ms | ActiveRecord: 0.0ms | Allocations: 249472)

Started POST "/users/sign_in" for 127.0.0.1 at 2020-12-17 11:26:21 -0600
Processing by SessionsController#create as HTML
  Parameters: {"authenticity_token"=>"IDqVSy1swedds22AEqMEzQQnamz7I+gysdfbNlPPhsRTMJGZkWCgWFYq1vg/3Af2Af5xjchnzdfgoH6m7wHXEA==", "user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Continue"}
  User Load (1.8ms)  SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "[email protected]"], ["LIMIT", 1]]
  ↳ app/controllers/sessions_controller.rb:6:in `create'
  User Load (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."email" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["email", "[email protected]"], ["LIMIT", 1]]
  ↳ app/controllers/sessions_controller.rb:11:in `create'
   (0.6ms)  BEGIN
  ↳ app/controllers/sessions_controller.rb:11:in `create'
  User Update (1.0ms)  UPDATE "users" SET "current_sign_in_at" = $1, "last_sign_in_at" = $2, "sign_in_count" = $3, "updated_at" = $4 WHERE "users"."id" = $5  [["current_sign_in_at", "2020-12-17 17:26:21.278696"], ["last_sign_in_at", "2020-12-17 17:24:43.660819"], ["sign_in_count", 31], ["updated_at", "2020-12-17 17:26:21.279770"], ["id", 2]]
  ↳ app/controllers/sessions_controller.rb:11:in `create'
   (4.6ms)  COMMIT
  ↳ app/controllers/sessions_controller.rb:11:in `create'
Redirected to 
Completed 500 Internal Server Error in 610ms (ActiveRecord: 9.9ms | Allocations: 188187)
NoMethodError (undefined method `user_url' for #
Did you mean?  search_url):
  
app/controllers/sessions_controller.rb:11:in `create'

UPDATE:

Mi sintaxis estaba ligeramente apagada, debería haber publicado el código exacto (sin saber):

  def after_sign_in_path_for(_resource=nil)
    return stored_location_for(resource) if stored_location_for(resource).present?
    return car_index_path if current_user.car?
    new_car_path
  end

Lo que está pasando es cuando stored_location_for(resource) se llama, se convierte en nil, y así el If declaración devuelve true, pero el valor almacenado_location_for(resource) devuelve nil.

Por lo tanto, causando el error. Stored_location_for() solución abajo funciona genial!

Pregunta hecha hace 3 años, 4 meses, 28 días - Por scriptsculptor52b5


3 Respuestas:

  • Pruebe a continuación con ayudador stored_location_for

    Devuelve y elimina (si es formato de navegación) el url almacenado en del período de sesiones el alcance dado. Útil para dar espaldas redireccionables después de registrarse:

    Según la idea wiki, por favor agregue el siguiente before_action en su aplicación_ controlador:

    class ApplicationController < ActionController::Base
      before_action :store_user_location!, if: :storable_location?
      
      def storable_location?
        request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
      end
    
      def store_user_location!
        store_location_for(:user, request.fullpath)
      end
    end
    

    Y luego en after_sign_in_path_for:

    def after_sign_in_path_for(resource = nil)
      stored_location_for(resource) || new_car_path
    end
    

    Respondida el Dec 17, 2020 a las 13:26 - por codecrafty

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que en el método after_sign_in_path_for estás utilizando stored_location_for(resource) sin definir previamente resource. Para solucionar esto puedes modificar tu método de la siguiente manera:

    ruby
    def after_sign_in_path_for(resource)
      stored_location = stored_location_for(resource)
      if stored_location
        stored_location
      else
        new_car_path
      end
    end
    

    De esta forma, primero obtienes el valor almacenado en stored_location_for(resource) y luego verificas si existe algún valor almacenado. Si hay un valor almacenado, redireccionarás al usuario a esa ruta, de lo contrario lo redirigirás a new_car_path.

    Además, en tu controlador de ApplicationController, puedes añadir la siguiente verificación para asegurarte de que el recurso esté definido antes de almacenar la ubicación:

    ruby
    def storable_location?
      request.get? && is_navigational_format? && !devise_controller? && !request.xhr? && !current_user.nil?
    end
    

    Esto garantizará que la ubicación solo se almacene cuando haya un usuario autenticado.

    Con estas modificaciones, tu código debería funcionar correctamente y redirigir al usuario a la página esperada después de la autenticación.

    Respondida el Dec 18, 2020 a las 13:26 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Problema:

    Parece que estás intentando redirigir a los usuarios a una página específica después de que inicien sesión, pero te encuentras con un error porque el método user_url no está definido en el controlador SessionsController.

    Solución:

    Para resolver este problema, puedes utilizar el método stored_location_for proporcionado por Devise. Este método almacena la URL de la página a la que el usuario intentaba acceder antes de ser redirigido al formulario de inicio de sesión.

    Para usar stored_location_for, agrega el siguiente código a tu controlador SessionsController en el método after_sign_in_path_for:

    
    def after_sign_in_path_for(_resource=nil)
      stored_location_for(resource) || new_car_path
    end
    

    Este código verificará si hay una ubicación almacenada para el usuario y lo redirigirá a esa página. Si no hay una ubicación almacenada, lo redirigirá a new_car_path.

    Acción antes:

    Además, para que el método stored_location_for funcione correctamente, debes agregar una acción antes al controlador ApplicationController para almacenar la ubicación actual:

    
    class ApplicationController < ActionController::Base
      before_action :store_user_location!, if: :storable_location?
    
      def storable_location?
        request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
      end
    
      def store_user_location!
        store_location_for(:user, request.fullpath)
      end
    end
    

    Esto almacenará la ubicación actual para el usuario en cada solicitud GET que no sea una solicitud de Devise o AJAX.

    Ejemplo actualizado:

    Tu código actualizado quedaría así:

    SessionsController

    
    class SessionsController < Devise::SessionsController
      def after_sign_in_path_for(_resource=nil)
        stored_location_for(resource) || new_car_path
      end
    end
    

    ApplicationController

    
    class ApplicationController < ActionController::Base
      before_action :store_user_location!, if: :storable_location?
    
      def storable_location?
        request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
      end
    
      def store_user_location!
        store_location_for(:user, request.fullpath)
      end
    end
    

    Con estos cambios, los usuarios ahora serán redirigidos a la página a la que intentaban acceder antes de iniciar sesión si esa página requiere autenticación.

    Respondida el Dec 18, 2020 a las 13:30 - por Gemini

    Votos positivos: 0 | Votos negativos: 0