Winston
Winston

Reputation: 41

Rails post multi-step form data after signup with Devise

I have a two step form that saves data in a session and creates a new record assuming the user is logged in.

If a new user hasn't signed up I want him to be able to:

  1. fill in form #1
  2. fill in form #2
  3. redirect to Devise signup (new_registration_path)
  4. post/create record from the form data after signup/login is completed

see code below (location_controller.rb):

On: "elsif @location.last_step?", it directs to signup if user isn't logged in but doesn't save the data after login.

Is there a way to pass the session form data thought Devise so it posts/creates the record after signup?

Thanks in advance

def new
  session[:location_params] ||= {}
    if current_user.nil?
      @location = Location.new(session[:location_params])
    else
      @location = current_user.locations.new(session[:location_params])
    end

  @location.current_step = session[:location_step]

  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @location }
  end   
end

def create
    session[:location_params].deep_merge!(params[:location]) if params[:location]
    if current_user.nil?
      @location = Location.new(session[:location_params])
    else
      @location = current_user.locations.new(session[:location_params])
    end
    @location.current_step = session[:location_step]
    if @location.valid?   
      if params[:back_button]
        @location.previous_step
      elsif @location.last_step?
       @location.save
      else
        @location.next_step
      end
      session[:location_step] = @location.current_step
    end

    if @location.new_record?
      render "new"
    else
      session[:location_step] = session[:location_params] = nil
      flash[:notice] = "Trip saved!"
      redirect_to @location
    end
  end

Upvotes: 3

Views: 1008

Answers (1)

Winston
Winston

Reputation: 41

I solved it:

  1. added store_form_data(@location) in locations.rb
  2. store_form_data function in SessionHelper (see below)
  3. added include SessionsHelper to application_controller.rb
  4. added def after_sign_in_path_for(resource) function in application_controller.rb (see blow)

app/helpers/session_helper.rb:

module SessionsHelper
  def store_form_data(locations)
    session[:form_data] = locations
  end
end

app/controllers/application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper

  def after_sign_in_path_for(resource)
    if session[:form_data].present?
      @user = current_user
      @location = session[:form_data]
      @user.locations << @location
      session[:form_data] = nil
      flash[:notice] = 'Trip saved!'
      index_path
    else
      new_location_path
    end
  end
end

apps/controllers/locations_controller.rb:

 def new
    #@location = Location.new
    session[:location_params] ||= {}
    session[:form_data] = nil
    if current_user.nil?
      @location = Location.new(session[:location_params])
    else
      @location = current_user.locations.new(session[:location_params])
    end

    @location.current_step = session[:location_step]

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @location }
    end
  end

def create
    session[:location_params].deep_merge!(params[:location]) if params[:location]
    if current_user.nil?
      @location = Location.new(session[:location_params])
    else
      @location = current_user.locations.new(session[:location_params])
    end
    @location.current_step = session[:location_step]
    if @location.valid?   
      if params[:back_button]
        @location.previous_step
      elsif @location.last_step?
        if current_user.nil?
          store_form_data(@location)
        end
       @location.save
      else
        @location.next_step
      end
      session[:location_step] = @location.current_step
    end

    if @location.new_record?
      render "new"
    else
      session[:location_step] = session[:location_params] = nil
      flash[:notice] = "Trip saved!"
      redirect_to @location
    end
  end

Upvotes: 1

Related Questions