web-dev-qa-db-ja.com

Deviseとstored_location_for:返品場所をどのように保存しますか?

ユーザーがログインしていない場合に「[ログイン]または[登録]してください」と表示しているパスが(例)/敷地/ 92のページがあり、同じものを返すように工夫したいユーザーがログインした後の/イベント/ 92ページ。

他の投稿を読んだことがありますが、deviseのstored_location_forがどのように機能するかを理解していると思います。理論的には、次のようなものをApplicationControllerに入れることができます。

def stored_location_for(resource)
  if (r = session[:return_to])
    session[:return_to] = nil
    r
  else
    super
  end
end

私の質問は、どのように/どこでセッション[:return_to]を設定するのですか?

ユーザーが[ログイン]または[登録]をクリックした場合にのみセッション[:return_to]を設定したいのですが、それを行うための最良の方法は何ですか?

  • リンクをJavaScriptで飾りますか?それはうまくいくかもしれませんが、手間がかかるようです。
  • ページをレンダリングする前に、Premises Controllerで設定しますか?それは正しくないようです。ユーザーが[ログイン]または[登録]リンクをクリックしないとどうなりますか?次に、session [:return_to]を奇妙な値に設定しました。これは、ユーザーが他のページからログインした場合にトリップする可能性があります。
  • [login]リンクと[register]リンクに?return_to=/premises/92クエリ文字列を追加し、RegistrationsControllerとSessionsControllerでそれを検出し、その情報を使用してsession [:return_to]を設定しますか?それはうまくいくように思えますが、手間もかかります。

これらの匂いはどれも正しくありません。 Stored_location_forの状態を設定するために一般的に受け入れられている手法は何ですか?

27
fearless_fool

使用法を考案する

session["#{scope}_return_to"]

したがって、認証のモデルがユーザーの場合は、session["user_return_to"]を使用できます。

25
rorra

私は、このデバイス全体のリダイレクトが非常に混乱していることに気づきました。

@rorraがDeviseが_session["#{scope}_return_to"]_を使用すると言っている場合、彼はDeviseのデフォルトのafter_sign_in_path_for(resource)がメソッドstored_location_for(resource)を介してその変数を使用することを意味します。

したがって、格納する場所を変数_session["#{scope}_return_to"]_に保存する必要があります。これは通常_session["user_return_to"]_になります。これを行うには、application_controller.rbに以下を配置します。

_after_action :store_location

def store_location
  # store last url - this is needed for post-login redirect to whatever the user last visited.
  if (request.fullpath != "/users/sign_in" &&
      request.fullpath != "/users/sign_up" &&
      request.fullpath != "/users/password" &&
      request.fullpath != "/users/sign_out" &&
      !request.xhr?) # don't store ajax calls
    session["user_return_to"] = request.fullpath 
  end
end
_

場合によっては、after_sign_in_path_for(resource)メソッドを定義する必要はありません。deviseのデフォルトメソッドがすべてのリダイレクトを実行し、リダイレクトURLが利用できない場合は、リソースルートパス(通常はユーザールート)にリダイレクトされます。パス)、それが存在しない場合は、ルートパスにリダイレクトされます。ただし、使用可能なリダイレクトURLがない場合にユーザーの送信先をカスタマイズする場合は、application_contorller.rbに以下を追加します(それに応じて_root_path_を変更します)。

_def after_sign_in_path_for(resource)
  stored_location_for(resource) || root_path
end
_
8
Jeremy Lynch

Deviseは、セッションでキー"#{resource}_return_to"を探します。

ここで私はAPIを引用しています:

デフォルトでは、最初にセッションで有効な#{resource}_return_toキーを見つけようとし、次に#{resource}_root_pathにフォールバックします。それ以外の場合は、root_pathを使用します。

ここにAPIへのリンクがあります

6
user566245

これが私が思いつくことができる最高のものです。 Facebook認証でも完全に機能します。セッション変数へのURLの先頭にさらに制限を追加することで、ユーザーに戻してほしくないパス(コールバック、スプラッシュページ、ランディングページなど)をさらに削除できます。

#ApplicationsController

after_filter :store_location

def store_location
  session[:previous_urls] ||= []
  # store unique urls only
  session[:previous_urls].prepend request.fullpath if session[:previous_urls].first != request.fullpath && request.fullpath != "/user" && request.fullpath != "/user/login" && request.fullpath != "/" && request.fullpath != "/user/logout" && request.fullpath != "/user/join" && request.fullpath != "/user/auth/facebook/callback"
  # For Rails < 3.2
  # session[:previous_urls].unshift request.fullpath if session[:previous_urls].first != request.fullpath 
  session[:previous_urls].pop if session[:previous_urls].count > 3
end

def after_sign_in_path_for(resource) 
  @url = session[:previous_urls].reverse.first
  if @url != nil
    "http://www.google.com" + @url
  else
    root_path
  end
end
4
ajbraus

私はこれが好きです:

class ApplicationController < AC::Base
  after_filter :clear_attached_unit # UPDATED

  protected
  def clear_attached_unit
    session[:attached_unit_path] = nil unless keep_attached_unit_path?
  end

  def keep_attached_unit_path? # UPDATED
    @keep_attached_unit_path   
  end                           
end


class UnitController < ApplicationController
  before_filter :attach_unit, :only => [:show]

  protected
  def attach_unit
    session[:attached_unit_path] = request.url if request.get? && !request.xhr?
  end
end

class SessionsController < Devise::SessionsController
  before_filter :keep_attached_unit_path! # UPDATED

  protected
  def keep_attached_unit_path! # UPDATED
    @keep_attached_unit_path = true
  end

  def after_sign_in_path_for(resource_or_scope)
    if resource_or_scope.is_a?(User) && session[:attached_unit_path].present?
      session[:attached_unit_path]
    else
      super
    end
  end 
end

そして、これをモジュールに抽出します。

1
Anton