Add store_location_for helper

This is used as a complement to `stored_location_for`.

Example:

Before authorizing with Omniauth;

  store_location_for(:user, dashboard_path)
  redirect_to user_omniauth_authorize_path(:facebook)

In our Omniauth callback

  sign_in(user)
  redirect_to stored_location_for(:user) || root_path
This commit is contained in:
Matthew Rudy Jacobs 2013-11-08 14:39:43 +00:00
parent e26ea51fe5
commit 268e486dbb
5 changed files with 61 additions and 18 deletions

View File

@ -21,6 +21,7 @@ module Devise
autoload :Rememberable, 'devise/controllers/rememberable' autoload :Rememberable, 'devise/controllers/rememberable'
autoload :ScopedViews, 'devise/controllers/scoped_views' autoload :ScopedViews, 'devise/controllers/scoped_views'
autoload :SignInOut, 'devise/controllers/sign_in_out' autoload :SignInOut, 'devise/controllers/sign_in_out'
autoload :StoreLocation, 'devise/controllers/store_location'
autoload :UrlHelpers, 'devise/controllers/url_helpers' autoload :UrlHelpers, 'devise/controllers/url_helpers'
end end

View File

@ -4,6 +4,7 @@ module Devise
module Helpers module Helpers
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Devise::Controllers::SignInOut include Devise::Controllers::SignInOut
include Devise::Controllers::StoreLocation
included do included do
helper_method :warden, :signed_in?, :devise_controller? helper_method :warden, :signed_in?, :devise_controller?
@ -97,23 +98,6 @@ module Devise
request.env["devise.allow_params_authentication"] = true request.env["devise.allow_params_authentication"] = true
end end
# 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:
#
# Example:
#
# redirect_to stored_location_for(:user) || root_path
#
def stored_location_for(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
if is_navigational_format?
session.delete("#{scope}_return_to")
else
session["#{scope}_return_to"]
end
end
# The scope root url to be used when he's signed in. By default, it first # The scope root url to be used when he's signed in. By default, it first
# tries to find a resource_root_path, otherwise it uses the root_path. # tries to find a resource_root_path, otherwise it uses the root_path.
def signed_in_root_path(resource_or_scope) def signed_in_root_path(resource_or_scope)

View File

@ -0,0 +1,45 @@
module Devise
module Controllers
# Provide the ability to store a location.
# Used to redirect back to a desired path after sign in.
# Included by default in all controllers.
module StoreLocation
# 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:
#
# Example:
#
# redirect_to stored_location_for(:user) || root_path
#
def stored_location_for(resource_or_scope)
session_key = stored_location_key_for(resource_or_scope)
if is_navigational_format?
session.delete(session_key)
else
session[session_key]
end
end
# Stores the provided location to redirect the user after signing in.
# Useful in combination with the `stored_location_for` helper.
#
# Example:
#
# store_location_for(:user, dashboard_path)
# redirect_to user_omniauth_authorize_path(:facebook)
#
def store_location_for(resource_or_scope, location)
session_key = stored_location_key_for(resource_or_scope)
session[session_key] = location
end
private
def stored_location_key_for(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
"#{scope}_return_to"
end
end
end
end

View File

@ -13,6 +13,8 @@ module Devise
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers
include Rails.application.routes.mounted_helpers include Rails.application.routes.mounted_helpers
include Devise::Controllers::StoreLocation
delegate :flash, :to => :request delegate :flash, :to => :request
def self.call(env) def self.call(env)
@ -189,7 +191,7 @@ module Devise
# yet, but we still need to store the uri based on scope, so different scopes # yet, but we still need to store the uri based on scope, so different scopes
# would never use the same uri to redirect. # would never use the same uri to redirect.
def store_location! def store_location!
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth? store_location_for(scope, attempted_path) if request.get? && !http_auth?
end end
def is_navigational_format? def is_navigational_format?

View File

@ -187,6 +187,17 @@ class ControllerAuthenticatableTest < ActionController::TestCase
assert_nil @controller.session[:"user_return_to"] assert_nil @controller.session[:"user_return_to"]
end end
test 'store location for stores a location to redirect back to' do
assert_nil @controller.stored_location_for(:user)
@controller.store_location_for(:user, "/foo.bar")
assert_equal "/foo.bar", @controller.stored_location_for(:user)
end
test 'store location for accepts a resource as argument' do
@controller.store_location_for(User.new, "/foo.bar")
assert_equal "/foo.bar", @controller.stored_location_for(User.new)
end
test 'after sign in path defaults to root path if none by was specified for the given scope' do test 'after sign in path defaults to root path if none by was specified for the given scope' do
assert_equal root_path, @controller.after_sign_in_path_for(:user) assert_equal root_path, @controller.after_sign_in_path_for(:user)
end end