在 sign_in 之后设计重定向并执行 POST 操作

Devise redirect after sign_in and perfom POST action

我正在使用 Devise gem & Rails 6.1 构建一个活动平台。 我在使用小型 RSVP 功能时遇到问题。

当非登录用户单击“参加”按钮时,它会将用户重定向到登录,完成后用户将重定向回上一页。但是,用户必须再次单击“参加”按钮。

我希望用户重定向回来并完成创建操作(POST 操作)

我成功地完成了重定向工作,但用户必须再次单击我不想要的“参加”按钮。我搜索了整个互联网,但 none 的解决方案有效。 我找到的壁橱解决方案来自这个博客https://blog.justinthiele.com/retaining-form-data-through-a-login-process-a/,我试图将其应用于我的应用程序但没有成功。

我认为 after_sign_in_path_for 方法中缺少某些东西。

如有任何帮助,我们将不胜感激。

更新!

调试后,我改变了一些覆盖 Devise 的方式。 我觉得我非常接近解决方案,但无法弄清楚我错过了什么。

attendee_controller.rb

    def create
      if !current_user
        # Store the data in the session so we can retrieve it after login
        session[:attendee] = params
        # Redirect the user to register/login
        redirect_to user_session_path
      else
        @attendee = current_user.attendees.build({event_id: params[:id]})

        respond_to do |format|
          AttendeeMailer.with(event: @attendee).notify_event_creator.deliver_now

          if @attendee.save
            format.html { redirect_to @attendee.event, notice: "You have successfully registered for the event!" }
            format.json { render :show, status: :created, location: @attendee }
          else
            format.html { render :new, status: :unprocessable_entity }
            format.json { render json: @attendee.errors, status: :unprocessable_entity }
          end
        end
      end
    end 

app\controllers\users\sessions_controller.rb (user_session_path)

   protected

  def after_sign_in_path_for(resource_or_scope)
    if session[:attendee].present?
      new_attributes = session[:attendee]
      previous_url = session[:previous_url] #defined in the show method from the events controller.

      @attendee = current_user.attendees.create({event_id: new_attributes[:id]})

      #clear session
      session[:attendee] = nil
      session[:previous_url] = nil
     
      previous_url
  else
    #if there is not temp attendee in the session proceed as normal
      super
    end
  end

events_controller.rb

def show 
 session[:previous_url] = request.fullpath
end

routes.rb

  devise_for :users, controllers: { sessions: "users/sessions" }
  resources :events do
    post :attendee, to: 'attendees#create', on: :member
    post :unattend, to: 'attendees#destroy', on: :member
  end

在浏览量中,views\events\show.html.erb

<%= button_to 'Attend Now', attendee_event_path(@event), class:"btn btn-success btn-lg" %>

找到解决方案! 实际上有一个名为 repost 的 gem,可帮助您重定向到 POST 操作。我在我的解决方案中实现了它。

这是我应用的全部技术。在 sign-in 之后重定向,然后在登录成功时完成 POST 操作:

首先,我创建一个会话 session[:previous_url] 以供稍后用于重定向回此处。

  def show
    session[:previous_url] = request.fullpath #url for user to come back after signing in
...

attendee_controller.rb :我们创建 session[:attendee]

   def create
    if !current_user
     session[:attendee] = true
     redirect_to user_session_path
   else
...

app\controllers\users\sessions_controller.rb (user_session_path)

protected

  def after_sign_in_path_for(resource_or_scope)
    if session[:attendee]
      previous_url = session[:previous_url]
      session[:previous_url] = nil #clear session
      previous_url #going back to event page
    else
      super
    end
  end

有关 after_sign_in_path_for 方法的更多信息,请参见 Devise How-To Wiki

previous_url 将使我们从事件中回到 show 视图。

这里是 gem 拯救世界的地方:

app\controllers\events_controller.rb

before_action :attendee?, only: :show

private

    def attendee?
      if session[:attendee]
        session[:attendee] = nil
        repost(attendee_event_path, options: {authenticity_token: :auto})
      end
    end

这是 gem 模板:

repost('url' , params: {}, options: {})

这里是 gem link: https://github.com/vergilet/repost