deviseの話です。
routes.rbにはこんなかんじの定義があるとします。
devise :users
resources :events do
resource :attendances, only: [:create, :destroy] # 参加処理
end
例えば、/events/new
にアクセスするにはuser
の認証が必要。そんな時はコントローラーに以下のように書きますよね。
class EventsController < ApplicationController
before_action :authenticate_user!, only: [:new] # rails3 以下なら before_filter
def show
# イベント表示処理
end
def new
# イベント作成準備処理
end
end
この時、ログインしてない状態で、/events/new
に アクセスすると、ログインしていないのでnew_user_session_path
にリダイレクトされますね。
んで、ログインした跡は、/events/new
に戻ってこれる。よい。devise
よい。
今度は、イベント参加時にuser
の認証が必要。そんな時は以下。
class AttendancesController < ApplicationController
before_action :set_event
before_action :authenticate_user! # rails3 以下なら before_filter
def create
# イベント参加処理
end
def destroy
# イベント参加キャンセル処理
end
private
def set_event
@event = Event.find(params[:event_id])
end
end
/events/:id
のview
に、こんなボタンが置いてあるイメージです。
= link_to(event_attendances_path(@event), method: :post, class: 'btn') do
= t('nav.attendaces.create')
この時、ログインしてない状態でこの参加ボタンをクリックすると、/events/:id/attendances
に POST
するわけですが、ログインしていないのでnew_user_session_path
にリダイレクトされますね。
んで、ログインすると、root_path
に戻ってしまうのがだるい。おれの参加したかったイベントよ、、、どこへ。本当なら、/events/:id
に戻りたいですよねーということで、そんな時どうするか。(前置きの長さよ)
磯野〜ソース読もうぜ〜
deviseのソースを読みましょう。
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
なるほどね、っと。session[:user_return_to]
に、/events/:id
を入れておけばうまくいきそうです。
イベント参加ボタンクリック後に、イベントページに戻る
参加処理のbefore_action
で session[:user_return_to]
に、/events/:id
を入れる処理をかきます。
class AttendancesController < ApplicationController
before_action :set_event
before_action :store_event_url # 追加!
before_action :authenticate_user! # rails3 以下なら before_filter
def create
# イベント参加処理
end
def destroy
# イベント参加キャンセル処理
end
private
def set_event
@event = Event.find(params[:event_id])
end
# 追加!
def store_event_url
session[:user_return_to] = event_path(@event) unless user_signed_in?
end
end
はい。こんな感じです。deviseの使っているsessionの中身を書き換えるのは怖いよ〜という方は好きにして下さい。