When a User signs in Devise taken to a new_car_path per the after_sign_in_path_for() method. However, there are situations where the User will try to go to a specific page that needs to be authenticated.
My example, logged out user goes directly to "domain.com/compliance-form", this page requires user to be authenticated before reaching it, so as expected, it redirects to a sign in form. When the user signs in, it takes them to the "after_sign_in_path_for" path, which in this care is the "new_car_path".
However, since the user know exactly the page they want to go to, I want them to go to "compliance_form_path" "domain.com/compliance-form".
How do I accomplish this?
def after_sign_in_path_for(_resource=nil)
new_car_path
end
If I add stored_location_for(resource)
as user11350468 recommended:
def after_sign_in_path_for(resource = nil)
stored_location_for(resource) || new_car_path
end
I get the following error,
NoMethodError in SessionsController#create undefined method `user_url' for #SessionsController:0x00007fc9f9bd1148 Did you mean? search_url
THen added:
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
Even after adding before action in controller, I get the same error, here are the logs..
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"=>"name@domain.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Continue"}
User Load (1.8ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "name@domain.com"], ["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", "name@domain.com"], ["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 #<SessionsController:0x00007fae28d6a438>
Did you mean? search_url):
app/controllers/sessions_controller.rb:11:in `create'
UPDATE:
My syntax was slightly off, I should have posted exact code (lesson learned):
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
What is happening is when stored_location_for(resource)
gets called, it becomes nil
, and so the If
statement returns true
, but the stored_location_for(resource) value returns nil
.
Hence causing the error. Stored_location_for() solution below works great!
Try the below with helper stored_location_for
Returns and delete (if it's navigational format) the url stored in the session for the given scope. Useful for giving redirect backs after sign up:
According to the the devise wiki, please add the below before_action
in your application_controller:
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
And then in after_sign_in_path_for:
def after_sign_in_path_for(resource = nil)
stored_location_for(resource) || new_car_path
end