BanditHijo.dev

Mempertahankan Data pada Form ketika User Belum Melakukan Authentication

Created at: 2020-01-01
Author by: BanditHijo

Prerequisite

ruby 2.6.3 rails 5.2.3 postgresql 11.5

Prakata

Mengawali tahun 2020 ini, saya mencatat mengenai Ruby on Rails.

Kali ini mengenai bagaimana cara memberikan user experience flow yang baik dengan web aplikasi yang menggunakan form saat pengguna belum melakukan authentication.

Permasalahan

Dalam mengisi form, misalkan form pemesanan (order), yang memiliki banyak inputan data, tentunya pengguna akan merasa kesal, apabila sudah memasukkan banyak data, namun saat menekan tombol submit, dan harus melakukan sign in atau sign up terlebih dahulu, setelah itu, data yang pengguna masukkan pada order form tadi sudah menghilang. Artinya, pengguna harus memasukkan kembali data-data yang sudah ia masukkan sebelumnya.

User experience flow di atas, tentunya akan membuat user merasa kesal.

Penyelesaian Masalah

Kebetulan, web aplikasi kali ini menggunakan Devise gem untuk menghandle proses authentication.1

Saya dapat memanfaatkan helper-helper module yang sudah disediakan oleh Devise.

Seperti, untuk membawa user kembali ke halaman sebelumnya, dengan stored_location_for dari Devise::Controllers::StoreLocation.

Untuk menyelesaikan permasalahan di atas, saya akan memodifikasi controller-controller yang menghandle proses-proses di atas.

Proses di atas terdiri dari:

  1. Order, yang dihandle oleh Users::OrderExperiencesController#create
  2. Sign In, yang dihandle oleh Users::SessionsController
  3. Sign Out, yang dihandle oleh Users::RegistrationsController

Bagaimana memertahankan data yang sudah dimasukkan sebelumnya pada Order form?

Untuk membuat data yang ada pada form menjadi persistent, saya akan memanfaatkan session.2 Kemudian, setelah user melakukan authentication, session akan di-passing ke dalam variable dan akan dikosongkan.

Order Experiences Controller

Karena proses order experience ini di-handle oleh action :create, maka saya perlu memodifikasi isi dari action ini.

app/controllers/users/order_experiences_controller.rb
1# frozen_string_literal: true
2
3class Users::OrderExperiencesController < ApplicationController
4 # pastikan untuk tidak memfilter action :create, karena akan dihandling oleh
5 # redirect rule yang akan dibuat
6 before_action :authenticate_user!, except: [:create]
7
8 def create
9 # mengecek apakah pengunjung sudah sign in/sign up
10 if current_user.nil?
11 # menyimpan data dari form ke dalam session, yang akan digunakan setelah login/register
12 session[:order] = params
13 # redirect ke user login/register page
14 redirect_to new_user_session_path
15 else
16 # jika user sudah login, diproses seperti biasa
17 order = current_traveler.orders.create(order_params)
18 redirect_to users_order_experience_path(order.id)
19 end
20 end
21
22 # ...
23 # ...
24
25 private
26
27 def order_params
28 params.require(:order).permit(
29 :trip_date, :time_slot, :total_traveler, :experience_id,
30 traveler_attributes: [:id, :full_name, :email, :phone]
31 )
32 end
33end

Pastikan pada callback before_action :authenticate_user!, buat pengecualian untuk action :create.

Selanjutnya, tinggal memodifikasi controller yang menghandle proses login/register.

Sessions & Registrations Controller

Kedua controller ini adalah controller yang digenerate oleh Devise.

app/controllers/users/sessions_controller.rb
1# frozen_string_literal: true
2
3class Users::SessionsController < Devise::SessionsController
4 # ...
5
6 # ...
7 # ...
8
9 protected
10
11 # ...
12 # ...
13
14 # path yang akan dituju setelah sign in
15 def after_sign_in_path_for(resource_or_scope)
16 # memeriksa apakah ada data order yang tersimpan pada session
17 if session[:order].present?
18 # membuat order dengan data yang tersimpan pada session
19 order = current_traveler.orders.create(session[:order]["order"])
20 # mengosongkan session
21 session[:order] = nil
22 # redirect ke halaman order
23 users_order_experience_path(order.id)
24 else
25 # jika tidak ada data order yang tersimpan pada session
26 stored_location_for(resource_or_scope) || super
27 end
28 end
29end
app/controllers/users/registrations_controller.rb
1# frozen_string_literal: true
2
3class Users::RegistrationsController < Devise::RegistrationsController
4 # ...
5
6 # ...
7 # ...
8
9 protected
10
11 # ...
12 # ...
13
14 # path yang akan dituju setelah sign up
15 def after_sign_up_path_for(resource_or_scope)
16 # memeriksa apakah ada data order yang tersimpan pada session
17 if session[:order].present?
18 # membuat order dengan data yang tersimpan pada session
19 @order = current_traveler.orders.create(session[:order]["order"])
20 # mengosongkan session
21 session[:order] = nil
22 # redirect ke halaman order
23 users_order_experience_path(@order.id)
24 else
25 # jika tidak ada data order yang tersimpan pada session
26 stored_location_for(resource_or_scope) || super
27 end
28 end
29
30 # ...
31 # ...
32end

Selesai!

Mungkin pada kesempatan yang lain, akan saya buatkan reponya.

Mudah-mudahan bermanfaat.

Terima kasih.

(^_^)

Referensi

  1. How To: Redirect back to current page after sign in, sign out, sign up, update
    Diakses tanggal: 2020/01/01

  2. Action Controller Overview > Session
    Diakses tanggal: 2020/01/01

  3. blog.justinthiele.com/retaining-form-data-through-a-login-process-a
    Diakses tanggal: 2020/01/01